http://reviews.llvm.org/D5365

Files:
  include/clang/AST/Expr.h
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/StmtProfile.cpp
  lib/CodeGen/CGExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/CodeGen/const-init.c
  test/CodeGen/func-in-block.c
  test/CodeGen/predefined-expr.c
  test/CodeGenCXX/funcsig.cpp
  test/CodeGenCXX/predefined-expr-cxx14.cpp
  test/CodeGenObjC/predefined-expr.m
Index: test/CodeGenCXX/predefined-expr-cxx14.cpp
===================================================================
--- test/CodeGenCXX/predefined-expr-cxx14.cpp
+++ test/CodeGenCXX/predefined-expr-cxx14.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -std=c++14 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
+
+// CHECK-DAG: private unnamed_addr constant [22 x i8] c"classTemplateFunction\00"
+// CHECK-DAG: private unnamed_addr constant [69 x i8] c"const auto &ClassTemplate<int>::classTemplateFunction(T &) [T = int]\00"
+
+// CHECK-DAG: private unnamed_addr constant [17 x i8] c"functionTemplate\00"
+// CHECK-DAG: private unnamed_addr constant [64 x i8] c"auto &ClassInTopLevelNamespace::functionTemplate(T &) [T = int]\00"
+
+// CHECK-DAG: private unnamed_addr constant [17 x i8] c"variadicFunction\00"
+// CHECK-DAG: private unnamed_addr constant [70 x i8] c"decltype(auto) ClassInTopLevelNamespace::variadicFunction(int *, ...)\00"
+
+// CHECK-DAG: private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00"
+// CHECK-DAG: private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00"
+
+int printf(const char * _Format, ...);
+
+class ClassInTopLevelNamespace {
+public:
+  auto *topLevelNamespaceFunction() {
+    printf("__func__ %s\n", __func__);
+    printf("__FUNCTION__ %s\n", __FUNCTION__);
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+    return static_cast<int *>(nullptr);
+  }
+
+  decltype(auto) variadicFunction(int *a, ...) {
+    printf("__func__ %s\n", __func__);
+    printf("__FUNCTION__ %s\n", __FUNCTION__);
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+    return a;
+  }
+
+  template<typename T>
+  auto &functionTemplate(T &t) {
+    printf("__func__ %s\n", __func__);
+    printf("__FUNCTION__ %s\n", __FUNCTION__);
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+    return t;
+  }
+};
+
+template<typename T>
+class ClassTemplate {
+public:
+  const auto &classTemplateFunction(T &t) {
+    printf("__func__ %s\n", __func__);
+    printf("__FUNCTION__ %s\n", __FUNCTION__);
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+    return t;
+  }
+};
+
+int main() {
+  int a;
+  ClassInTopLevelNamespace topLevelNamespace;
+  topLevelNamespace.topLevelNamespaceFunction();
+  topLevelNamespace.variadicFunction(&a);
+  topLevelNamespace.functionTemplate(a);
+
+  ClassTemplate<int> t;
+  t.classTemplateFunction(a);
+  return 0;
+}
Index: test/CodeGenCXX/funcsig.cpp
===================================================================
--- test/CodeGenCXX/funcsig.cpp
+++ test/CodeGenCXX/funcsig.cpp
@@ -8,22 +8,22 @@
 void freeFunc(int *, char) {
   printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
 }
-// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
+// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
 
 struct TopLevelClass {
   void topLevelMethod(int *, char);
 };
 void TopLevelClass::topLevelMethod(int *, char) {
   printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
 }
-// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
+// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
 
 namespace NS {
 struct NamespacedClass {
   void namespacedMethod(int *, char);
 };
 void NamespacedClass::namespacedMethod(int *, char) {
   printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
 }
-// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
+// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
 }
Index: test/CodeGenObjC/predefined-expr.m
===================================================================
--- test/CodeGenObjC/predefined-expr.m
+++ test/CodeGenObjC/predefined-expr.m
@@ -1,15 +1,15 @@
 // RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 %s -emit-llvm -o - | FileCheck %s
 
-// CHECK: @"__func__.-[Foo instanceTest1]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest1]\00"
-// CHECK: @"__func__.-[Foo instanceTest2:]" = private unnamed_addr constant [22 x i8] c"-[Foo instanceTest2:]\00"
-// CHECK: @"__func__.-[Foo instanceTest3:withB:]" = private unnamed_addr constant [28 x i8] c"-[Foo instanceTest3:withB:]\00"
-// CHECK: @"__func__.-[Foo instanceTest4]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest4]\00"
-// CHECK: @"__func__.+[Foo classTest1]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest1]\00"
-// CHECK: @"__func__.+[Foo classTest2:]" = private unnamed_addr constant [19 x i8] c"+[Foo classTest2:]\00"
-// CHECK: @"__func__.+[Foo classTest3:withB:]" = private unnamed_addr constant [25 x i8] c"+[Foo classTest3:withB:]\00"
-// CHECK: @"__func__.+[Foo classTest4]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest4]\00"
-// CHECK: @"__func__.-[Foo(Category) instanceTestWithCategory]" = private unnamed_addr constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00"
-// CHECK: @"__func__.+[Foo(Category) classTestWithCategory]" = private unnamed_addr constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00"
+// CHECK: private unnamed_addr constant [21 x i8] c"-[Foo instanceTest1]\00"
+// CHECK: private unnamed_addr constant [22 x i8] c"-[Foo instanceTest2:]\00"
+// CHECK: private unnamed_addr constant [28 x i8] c"-[Foo instanceTest3:withB:]\00"
+// CHECK: private unnamed_addr constant [21 x i8] c"-[Foo instanceTest4]\00"
+// CHECK: private unnamed_addr constant [18 x i8] c"+[Foo classTest1]\00"
+// CHECK: private unnamed_addr constant [19 x i8] c"+[Foo classTest2:]\00"
+// CHECK: private unnamed_addr constant [25 x i8] c"+[Foo classTest3:withB:]\00"
+// CHECK: private unnamed_addr constant [18 x i8] c"+[Foo classTest4]\00"
+// CHECK: private unnamed_addr constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00"
+// CHECK: private unnamed_addr constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00"
 
 int printf(const char * _Format, ...);
 
Index: test/CodeGen/const-init.c
===================================================================
--- test/CodeGen/const-init.c
+++ test/CodeGen/const-init.c
@@ -121,8 +121,8 @@
 struct g23 {char a; short b; char c; struct g22 d;};
 struct g23 g24 = {1,2,3,4};
 
-// CHECK: @g25.g26 = internal global i8* getelementptr inbounds ([4 x i8]* @__func__.g25, i32 0, i32 0)
-// CHECK: @__func__.g25 = private unnamed_addr constant [4 x i8] c"g25\00"
+// CHECK: @g25.g26 = internal global i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0)
+// CHECK: @.str = private unnamed_addr constant [4 x i8] c"g25\00"
 int g25() {
   static const char *g26 = __func__;
   return *g26;
@@ -153,7 +153,7 @@
       DCC_PASSWD passwd;
   } DCC_SRVR_NM;
   // CHECK: @g29.a = internal global %struct.DCC_SRVR_NM { [2 x i8] c"@\00" }, align 1
-  // CHECK: @g29.b = internal global [1 x i32] [i32 ptrtoint ([5 x i8]* @.str to i32)], align 4
+  // CHECK: @g29.b = internal global [1 x i32] [i32 ptrtoint ([5 x i8]* @.str1 to i32)], align 4
   // CHECK: @g29.c = internal global [1 x i32] [i32 97], align 4
   static DCC_SRVR_NM a = { {"@"} };
   static int b[1] = { "asdf" }; // expected-warning {{incompatible pointer to integer conversion initializing 'int' with an expression of type 'char [5]'}}
Index: test/CodeGen/func-in-block.c
===================================================================
--- test/CodeGen/func-in-block.c
+++ test/CodeGen/func-in-block.c
@@ -15,5 +15,5 @@
     return 0; // not reached
 }
 
-// CHECK: @__func__.__main_block_invoke = private unnamed_addr constant [20 x i8] c"__main_block_invoke\00"
-// CHECK: call void @PRINTF({{.*}}@__func__.__main_block_invoke 
+// CHECK: @[[FUNC:.+]] = private unnamed_addr constant [5 x i8] c"main\00"
+// CHECK: call void @PRINTF({{.*}}@[[FUNC]] 
Index: test/CodeGen/predefined-expr.c
===================================================================
--- test/CodeGen/predefined-expr.c
+++ test/CodeGen/predefined-expr.c
@@ -1,16 +1,16 @@
 // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 -fms-extensions %s -emit-llvm -o - | FileCheck %s
 
-// CHECK: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00"
-// CHECK: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [21 x i8] c"void plainFunction()\00"
-// CHECK: @__func__.externFunction = private unnamed_addr constant [15 x i8] c"externFunction\00"
-// CHECK: @__PRETTY_FUNCTION__.externFunction = private unnamed_addr constant [22 x i8] c"void externFunction()\00"
-// CHECK: @__func__.privateExternFunction = private unnamed_addr constant [22 x i8] c"privateExternFunction\00"
-// CHECK: @__PRETTY_FUNCTION__.privateExternFunction = private unnamed_addr constant [29 x i8] c"void privateExternFunction()\00"
-// CHECK: @__func__.__captured_stmt = private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00"
-// CHECK: @__PRETTY_FUNCTION__.__captured_stmt = private unnamed_addr constant [32 x i8] c"void functionWithCapturedStmt()\00"
-// CHECK: @__func__.staticFunction = private unnamed_addr constant [15 x i8] c"staticFunction\00"
-// CHECK: @__PRETTY_FUNCTION__.staticFunction = private unnamed_addr constant [22 x i8] c"void staticFunction()\00"
+// CHECK: private unnamed_addr constant [14 x i8] c"plainFunction\00"
+// CHECK: private unnamed_addr constant [21 x i8] c"void plainFunction()\00"
+// CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00"
+// CHECK: private unnamed_addr constant [22 x i8] c"void externFunction()\00"
+// CHECK: private unnamed_addr constant [22 x i8] c"privateExternFunction\00"
+// CHECK: private unnamed_addr constant [29 x i8] c"void privateExternFunction()\00"
+// CHECK: private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00"
+// CHECK: private unnamed_addr constant [32 x i8] c"void functionWithCapturedStmt()\00"
+// CHECK: private unnamed_addr constant [15 x i8] c"staticFunction\00"
+// CHECK: private unnamed_addr constant [22 x i8] c"void staticFunction()\00"
 
 int printf(const char *, ...);
 
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -1161,55 +1161,6 @@
   friend class ASTStmtWriter;
 };
 
-/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
-class PredefinedExpr : public Expr {
-public:
-  enum IdentType {
-    Func,
-    Function,
-    LFunction,  // Same as Function, but as wide string.
-    FuncDName,
-    FuncSig,
-    PrettyFunction,
-    /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
-    /// 'virtual' keyword is omitted for virtual member functions.
-    PrettyFunctionNoVirtual
-  };
-
-private:
-  SourceLocation Loc;
-  IdentType Type;
-public:
-  PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
-    : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
-           type->isDependentType(), type->isDependentType(),
-           type->isInstantiationDependentType(),
-           /*ContainsUnexpandedParameterPack=*/false),
-      Loc(l), Type(IT) {}
-
-  /// \brief Construct an empty predefined expression.
-  explicit PredefinedExpr(EmptyShell Empty)
-    : Expr(PredefinedExprClass, Empty) { }
-
-  IdentType getIdentType() const { return Type; }
-  void setIdentType(IdentType IT) { Type = IT; }
-
-  SourceLocation getLocation() const { return Loc; }
-  void setLocation(SourceLocation L) { Loc = L; }
-
-  static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
-
-  SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
-  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
-
-  static bool classof(const Stmt *T) {
-    return T->getStmtClass() == PredefinedExprClass;
-  }
-
-  // Iterators
-  child_range children() { return child_range(); }
-};
-
 /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
 /// leaking memory.
 ///
@@ -1603,6 +1554,62 @@
   child_range children() { return child_range(); }
 };
 
+/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr : public Expr {
+public:
+  enum IdentType {
+    Func,
+    Function,
+    LFunction,  // Same as Function, but as wide string.
+    FuncDName,
+    FuncSig,
+    PrettyFunction,
+    /// \brief The same as PrettyFunction, except that the
+    /// 'virtual' keyword is omitted for virtual member functions.
+    PrettyFunctionNoVirtual
+  };
+
+private:
+  SourceLocation Loc;
+  IdentType Type;
+  Stmt *StringLit;
+public:
+  PredefinedExpr(SourceLocation L, QualType T, IdentType IT, StringLiteral *SL)
+    : Expr(PredefinedExprClass, T, VK_LValue, OK_Ordinary,
+           T->isDependentType(), T->isDependentType(),
+           T->isInstantiationDependentType(),
+           /*ContainsUnexpandedParameterPack=*/false),
+      Loc(L), Type(IT), StringLit(SL) {}
+
+  /// \brief Construct an empty predefined expression.
+  explicit PredefinedExpr(EmptyShell Empty)
+    : Expr(PredefinedExprClass, Empty) { }
+
+  IdentType getIdentType() const { return Type; }
+  void setIdentType(IdentType IT) { Type = IT; }
+
+  SourceLocation getLocation() const { return Loc; }
+  void setLocation(SourceLocation L) { Loc = L; }
+
+  const StringLiteral *getStringLiteral() const {
+    return cast<StringLiteral>(StringLit);
+  }
+  StringLiteral *getStringLiteral() { return cast<StringLiteral>(StringLit); }
+  void setStringLiteral(StringLiteral *SL) { StringLit = SL; }
+
+  static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
+
+  SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == PredefinedExprClass;
+  }
+
+  // Iterators
+  child_range children() { return child_range(&StringLit, &StringLit + 1); }
+};
+
 /// ParenExpr - This represents a parethesized expression, e.g. "(1)".  This
 /// AST node is only formed if full location information is requested.
 class ParenExpr : public Expr {
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -6964,7 +6964,7 @@
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
-  return E;
+  return getDerived().TransformPredefinedExpr(E);
 }
 
 template<typename Derived>
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -42,6 +42,7 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaFixItUtils.h"
 #include "clang/Sema/Template.h"
+#include "llvm/Support/ConvertUTF.h"
 using namespace clang;
 using namespace sema;
 
@@ -2901,6 +2902,17 @@
   }
 }
 
+static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
+                                    SmallString<32> &Target) {
+  Target.resize(CharByteWidth * (Source.size() + 1));
+  char *ResultPtr = &Target[0];
+  const UTF8 *ErrorPtr;
+  bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
+  (void)success;
+  assert(success);
+  Target.resize(ResultPtr - &Target[0]);
+}
+
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
                                      PredefinedExpr::IdentType IT) {
   // Pick the current block, lambda, captured statement or function.
@@ -2920,22 +2932,36 @@
   }
 
   QualType ResTy;
+  StringLiteral *SL = nullptr;
   if (cast<DeclContext>(currentDecl)->isDependentContext())
     ResTy = Context.DependentTy;
   else {
     // Pre-defined identifiers are of type char[x], where x is the length of
     // the string.
-    unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+    auto Str = PredefinedExpr::ComputeName(IT, currentDecl);
+    unsigned Length = Str.length();
 
     llvm::APInt LengthI(32, Length + 1);
-    if (IT == PredefinedExpr::LFunction)
+    if (IT == PredefinedExpr::LFunction) {
       ResTy = Context.WideCharTy.withConst();
-    else
+      SmallString<32> RawChars;
+      ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
+                              Str, RawChars);
+      ResTy =
+          Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+      SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
+                                 /*Pascal = */ false, ResTy, Loc);
+
+    } else {
       ResTy = Context.CharTy.withConst();
-    ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+      ResTy =
+          Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+      SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
+                                 /*Pascal = */ false, ResTy, Loc);
+    }
   }
 
-  return new (Context) PredefinedExpr(Loc, ResTy, IT);
+  return new (Context) PredefinedExpr(Loc, ResTy, IT, SL);
 }
 
 ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -2021,7 +2021,9 @@
 /// Extract the value of a character from a string literal.
 static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
                                             uint64_t Index) {
-  // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+  // FIXME: Support ObjCEncodeExpr, MakeStringConstant
+  if (auto *PE = dyn_cast<PredefinedExpr>(Lit))
+    Lit = PE->getStringLiteral();
   const StringLiteral *S = cast<StringLiteral>(Lit);
   const ConstantArrayType *CAT =
       Info.Ctx.getAsConstantArrayType(S->getType());
@@ -2649,10 +2651,10 @@
         return false;
       CompleteObject LitObj(&Lit, Base->getType());
       return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal);
-    } else if (isa<StringLiteral>(Base)) {
+    } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {
       // We represent a string literal array as an lvalue pointing at the
       // corresponding expression, rather than building an array of chars.
-      // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+      // FIXME: Support ObjCEncodeExpr, MakeStringConstant
       APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
       CompleteObject StrObj(&Str, Base->getType());
       return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal);
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -469,6 +469,7 @@
 void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
   VisitExpr(S);
   ID.AddInteger(S->getIdentType());
+  VisitStringLiteral(S->getStringLiteral());
 }
 
 void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -448,214 +448,6 @@
   return getNameInfo().getLocEnd();
 }
 
-// FIXME: Maybe this should use DeclPrinter with a special "print predefined
-// expr" policy instead.
-std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
-  ASTContext &Context = CurrentDecl->getASTContext();
-
-  if (IT == PredefinedExpr::FuncDName) {
-    if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
-      std::unique_ptr<MangleContext> MC;
-      MC.reset(Context.createMangleContext());
-
-      if (MC->shouldMangleDeclName(ND)) {
-        SmallString<256> Buffer;
-        llvm::raw_svector_ostream Out(Buffer);
-        if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
-          MC->mangleCXXCtor(CD, Ctor_Base, Out);
-        else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
-          MC->mangleCXXDtor(DD, Dtor_Base, Out);
-        else
-          MC->mangleName(ND, Out);
-
-        Out.flush();
-        if (!Buffer.empty() && Buffer.front() == '\01')
-          return Buffer.substr(1);
-        return Buffer.str();
-      } else
-        return ND->getIdentifier()->getName();
-    }
-    return "";
-  }
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
-    if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
-      return FD->getNameAsString();
-
-    SmallString<256> Name;
-    llvm::raw_svector_ostream Out(Name);
-
-    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-      if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
-        Out << "virtual ";
-      if (MD->isStatic())
-        Out << "static ";
-    }
-
-    PrintingPolicy Policy(Context.getLangOpts());
-    std::string Proto;
-    llvm::raw_string_ostream POut(Proto);
-
-    const FunctionDecl *Decl = FD;
-    if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
-      Decl = Pattern;
-    const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
-    const FunctionProtoType *FT = nullptr;
-    if (FD->hasWrittenPrototype())
-      FT = dyn_cast<FunctionProtoType>(AFT);
-
-    if (IT == FuncSig) {
-      switch (FT->getCallConv()) {
-      case CC_C: POut << "__cdecl "; break;
-      case CC_X86StdCall: POut << "__stdcall "; break;
-      case CC_X86FastCall: POut << "__fastcall "; break;
-      case CC_X86ThisCall: POut << "__thiscall "; break;
-      // Only bother printing the conventions that MSVC knows about.
-      default: break;
-      }
-    }
-
-    FD->printQualifiedName(POut, Policy);
-
-    POut << "(";
-    if (FT) {
-      for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
-        if (i) POut << ", ";
-        POut << Decl->getParamDecl(i)->getType().stream(Policy);
-      }
-
-      if (FT->isVariadic()) {
-        if (FD->getNumParams()) POut << ", ";
-        POut << "...";
-      }
-    }
-    POut << ")";
-
-    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-      const FunctionType *FT = MD->getType()->castAs<FunctionType>();
-      if (FT->isConst())
-        POut << " const";
-      if (FT->isVolatile())
-        POut << " volatile";
-      RefQualifierKind Ref = MD->getRefQualifier();
-      if (Ref == RQ_LValue)
-        POut << " &";
-      else if (Ref == RQ_RValue)
-        POut << " &&";
-    }
-
-    typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
-    SpecsTy Specs;
-    const DeclContext *Ctx = FD->getDeclContext();
-    while (Ctx && isa<NamedDecl>(Ctx)) {
-      const ClassTemplateSpecializationDecl *Spec
-                               = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
-      if (Spec && !Spec->isExplicitSpecialization())
-        Specs.push_back(Spec);
-      Ctx = Ctx->getParent();
-    }
-
-    std::string TemplateParams;
-    llvm::raw_string_ostream TOut(TemplateParams);
-    for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
-         I != E; ++I) {
-      const TemplateParameterList *Params 
-                  = (*I)->getSpecializedTemplate()->getTemplateParameters();
-      const TemplateArgumentList &Args = (*I)->getTemplateArgs();
-      assert(Params->size() == Args.size());
-      for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) {
-        StringRef Param = Params->getParam(i)->getName();
-        if (Param.empty()) continue;
-        TOut << Param << " = ";
-        Args.get(i).print(Policy, TOut);
-        TOut << ", ";
-      }
-    }
-
-    FunctionTemplateSpecializationInfo *FSI 
-                                          = FD->getTemplateSpecializationInfo();
-    if (FSI && !FSI->isExplicitSpecialization()) {
-      const TemplateParameterList* Params 
-                                  = FSI->getTemplate()->getTemplateParameters();
-      const TemplateArgumentList* Args = FSI->TemplateArguments;
-      assert(Params->size() == Args->size());
-      for (unsigned i = 0, e = Params->size(); i != e; ++i) {
-        StringRef Param = Params->getParam(i)->getName();
-        if (Param.empty()) continue;
-        TOut << Param << " = ";
-        Args->get(i).print(Policy, TOut);
-        TOut << ", ";
-      }
-    }
-
-    TOut.flush();
-    if (!TemplateParams.empty()) {
-      // remove the trailing comma and space
-      TemplateParams.resize(TemplateParams.size() - 2);
-      POut << " [" << TemplateParams << "]";
-    }
-
-    POut.flush();
-
-    // Print "auto" for all deduced return types. This includes C++1y return
-    // type deduction and lambdas. For trailing return types resolve the
-    // decltype expression. Otherwise print the real type when this is
-    // not a constructor or destructor.
-    if ((isa<CXXMethodDecl>(FD) &&
-         cast<CXXMethodDecl>(FD)->getParent()->isLambda()) ||
-        (FT && FT->getReturnType()->getAs<AutoType>()))
-      Proto = "auto " + Proto;
-    else if (FT && FT->getReturnType()->getAs<DecltypeType>())
-      FT->getReturnType()
-          ->getAs<DecltypeType>()
-          ->getUnderlyingType()
-          .getAsStringInternal(Proto, Policy);
-    else if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
-      AFT->getReturnType().getAsStringInternal(Proto, Policy);
-
-    Out << Proto;
-
-    Out.flush();
-    return Name.str().str();
-  }
-  if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) {
-    for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent())
-      // Skip to its enclosing function or method, but not its enclosing
-      // CapturedDecl.
-      if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) {
-        const Decl *D = Decl::castFromDeclContext(DC);
-        return ComputeName(IT, D);
-      }
-    llvm_unreachable("CapturedDecl not inside a function or method");
-  }
-  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
-    SmallString<256> Name;
-    llvm::raw_svector_ostream Out(Name);
-    Out << (MD->isInstanceMethod() ? '-' : '+');
-    Out << '[';
-
-    // For incorrect code, there might not be an ObjCInterfaceDecl.  Do
-    // a null check to avoid a crash.
-    if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
-      Out << *ID;
-
-    if (const ObjCCategoryImplDecl *CID =
-        dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
-      Out << '(' << *CID << ')';
-
-    Out <<  ' ';
-    MD->getSelector().print(Out);
-    Out <<  ']';
-
-    Out.flush();
-    return Name.str().str();
-  }
-  if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
-    // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
-    return "top level";
-  }
-  return "";
-}
-
 void APNumericStorage::setIntValue(const ASTContext &C,
                                    const llvm::APInt &Val) {
   if (hasAllocation())
@@ -1017,7 +809,212 @@
   }
 }
 
+// FIXME: Maybe this should use DeclPrinter with a special "print predefined
+// expr" policy instead.
+std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
+  ASTContext &Context = CurrentDecl->getASTContext();
+
+  if (IT == PredefinedExpr::FuncDName) {
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
+      std::unique_ptr<MangleContext> MC;
+      MC.reset(Context.createMangleContext());
+
+      if (MC->shouldMangleDeclName(ND)) {
+        SmallString<256> Buffer;
+        llvm::raw_svector_ostream Out(Buffer);
+        if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
+          MC->mangleCXXCtor(CD, Ctor_Base, Out);
+        else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
+          MC->mangleCXXDtor(DD, Dtor_Base, Out);
+        else
+          MC->mangleName(ND, Out);
+
+        Out.flush();
+        if (!Buffer.empty() && Buffer.front() == '\01')
+          return Buffer.substr(1);
+        return Buffer.str();
+      } else
+        return ND->getIdentifier()->getName();
+    }
+    return "";
+  }
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
+    if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
+      return FD->getNameAsString();
+
+    SmallString<256> Name;
+    llvm::raw_svector_ostream Out(Name);
+
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
+        Out << "virtual ";
+      if (MD->isStatic())
+        Out << "static ";
+    }
+
+    PrintingPolicy Policy(Context.getLangOpts());
+    std::string Proto;
+    llvm::raw_string_ostream POut(Proto);
+
+    const FunctionDecl *Decl = FD;
+    if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
+      Decl = Pattern;
+    const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
+    const FunctionProtoType *FT = nullptr;
+    if (FD->hasWrittenPrototype())
+      FT = dyn_cast<FunctionProtoType>(AFT);
+
+    if (IT == FuncSig) {
+      switch (FT->getCallConv()) {
+      case CC_C: POut << "__cdecl "; break;
+      case CC_X86StdCall: POut << "__stdcall "; break;
+      case CC_X86FastCall: POut << "__fastcall "; break;
+      case CC_X86ThisCall: POut << "__thiscall "; break;
+      // Only bother printing the conventions that MSVC knows about.
+      default: break;
+      }
+    }
+
+    FD->printQualifiedName(POut, Policy);
+
+    POut << "(";
+    if (FT) {
+      for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
+        if (i) POut << ", ";
+        POut << Decl->getParamDecl(i)->getType().stream(Policy);
+      }
+
+      if (FT->isVariadic()) {
+        if (FD->getNumParams()) POut << ", ";
+        POut << "...";
+      }
+    }
+    POut << ")";
+
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      const FunctionType *FT = MD->getType()->castAs<FunctionType>();
+      if (FT->isConst())
+        POut << " const";
+      if (FT->isVolatile())
+        POut << " volatile";
+      RefQualifierKind Ref = MD->getRefQualifier();
+      if (Ref == RQ_LValue)
+        POut << " &";
+      else if (Ref == RQ_RValue)
+        POut << " &&";
+    }
+
+    typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
+    SpecsTy Specs;
+    const DeclContext *Ctx = FD->getDeclContext();
+    while (Ctx && isa<NamedDecl>(Ctx)) {
+      const ClassTemplateSpecializationDecl *Spec
+                               = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
+      if (Spec && !Spec->isExplicitSpecialization())
+        Specs.push_back(Spec);
+      Ctx = Ctx->getParent();
+    }
+
+    std::string TemplateParams;
+    llvm::raw_string_ostream TOut(TemplateParams);
+    for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
+         I != E; ++I) {
+      const TemplateParameterList *Params 
+                  = (*I)->getSpecializedTemplate()->getTemplateParameters();
+      const TemplateArgumentList &Args = (*I)->getTemplateArgs();
+      assert(Params->size() == Args.size());
+      for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) {
+        StringRef Param = Params->getParam(i)->getName();
+        if (Param.empty()) continue;
+        TOut << Param << " = ";
+        Args.get(i).print(Policy, TOut);
+        TOut << ", ";
+      }
+    }
+
+    FunctionTemplateSpecializationInfo *FSI 
+                                          = FD->getTemplateSpecializationInfo();
+    if (FSI && !FSI->isExplicitSpecialization()) {
+      const TemplateParameterList* Params 
+                                  = FSI->getTemplate()->getTemplateParameters();
+      const TemplateArgumentList* Args = FSI->TemplateArguments;
+      assert(Params->size() == Args->size());
+      for (unsigned i = 0, e = Params->size(); i != e; ++i) {
+        StringRef Param = Params->getParam(i)->getName();
+        if (Param.empty()) continue;
+        TOut << Param << " = ";
+        Args->get(i).print(Policy, TOut);
+        TOut << ", ";
+      }
+    }
+
+    TOut.flush();
+    if (!TemplateParams.empty()) {
+      // remove the trailing comma and space
+      TemplateParams.resize(TemplateParams.size() - 2);
+      POut << " [" << TemplateParams << "]";
+    }
+
+    POut.flush();
+
+    // Print "auto" for all deduced return types. This includes C++1y return
+    // type deduction and lambdas. For trailing return types resolve the
+    // decltype expression. Otherwise print the real type when this is
+    // not a constructor or destructor.
+    if (isa<CXXMethodDecl>(FD) &&
+         cast<CXXMethodDecl>(FD)->getParent()->isLambda())
+      Proto = "auto " + Proto;
+    else if (FT && FT->getReturnType()->getAs<DecltypeType>())
+      FT->getReturnType()
+          ->getAs<DecltypeType>()
+          ->getUnderlyingType()
+          .getAsStringInternal(Proto, Policy);
+    else if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
+      AFT->getReturnType().getAsStringInternal(Proto, Policy);
+
+    Out << Proto;
 
+    Out.flush();
+    return Name.str().str();
+  }
+  if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) {
+    for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent())
+      // Skip to its enclosing function or method, but not its enclosing
+      // CapturedDecl.
+      if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) {
+        const Decl *D = Decl::castFromDeclContext(DC);
+        return ComputeName(IT, D);
+      }
+    llvm_unreachable("CapturedDecl not inside a function or method");
+  }
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
+    SmallString<256> Name;
+    llvm::raw_svector_ostream Out(Name);
+    Out << (MD->isInstanceMethod() ? '-' : '+');
+    Out << '[';
+
+    // For incorrect code, there might not be an ObjCInterfaceDecl.  Do
+    // a null check to avoid a crash.
+    if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
+      Out << *ID;
+
+    if (const ObjCCategoryImplDecl *CID =
+        dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
+      Out << '(' << *CID << ')';
+
+    Out <<  ' ';
+    MD->getSelector().print(Out);
+    Out <<  ']';
+
+    Out.flush();
+    return Name.str().str();
+  }
+  if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
+    // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
+    return "top level";
+  }
+  return "";
+}
 
 /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
 /// corresponds to, e.g. "sizeof" or "[pre]++".
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -864,7 +864,6 @@
     case Stmt::ObjCProtocolExprClass:
     case Stmt::ObjCSelectorExprClass:
     case Stmt::ParenListExprClass:
-    case Stmt::PredefinedExprClass:
     case Stmt::ShuffleVectorExprClass:
     case Stmt::ConvertVectorExprClass:
     case Stmt::VAArgExprClass:
@@ -876,6 +875,7 @@
 
     // Cases we intentionally don't evaluate, since they don't need
     // to be explicitly evaluated.
+    case Stmt::PredefinedExprClass:
     case Stmt::AddrLabelExprClass:
     case Stmt::AttributedStmtClass:
     case Stmt::IntegerLiteralClass:
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -2051,86 +2051,10 @@
                         E->getType());
 }
 
-static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
-                                    SmallString<32>& Target) {
-  Target.resize(CharByteWidth * (Source.size() + 1));
-  char *ResultPtr = &Target[0];
-  const UTF8 *ErrorPtr;
-  bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
-  (void)success;
-  assert(success);
-  Target.resize(ResultPtr - &Target[0]);
-}
-
 LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
-  switch (E->getIdentType()) {
-  default:
-    return EmitUnsupportedLValue(E, "predefined expression");
-
-  case PredefinedExpr::Func:
-  case PredefinedExpr::Function:
-  case PredefinedExpr::LFunction:
-  case PredefinedExpr::FuncDName:
-  case PredefinedExpr::FuncSig:
-  case PredefinedExpr::PrettyFunction: {
-    PredefinedExpr::IdentType IdentType = E->getIdentType();
-    std::string GVName;
-
-    // FIXME: We should use the string literal mangling for the Microsoft C++
-    // ABI so that strings get merged.
-    switch (IdentType) {
-    default: llvm_unreachable("Invalid type");
-    case PredefinedExpr::Func:           GVName = "__func__."; break;
-    case PredefinedExpr::Function:       GVName = "__FUNCTION__."; break;
-    case PredefinedExpr::FuncDName:      GVName = "__FUNCDNAME__."; break;
-    case PredefinedExpr::FuncSig:        GVName = "__FUNCSIG__."; break;
-    case PredefinedExpr::LFunction:      GVName = "L__FUNCTION__."; break;
-    case PredefinedExpr::PrettyFunction: GVName = "__PRETTY_FUNCTION__."; break;
-    }
-
-    StringRef FnName = CurFn->getName();
-    if (FnName.startswith("\01"))
-      FnName = FnName.substr(1);
-    GVName += FnName;
-
-    // If this is outside of a function use the top level decl.
-    const Decl *CurDecl = CurCodeDecl;
-    if (!CurDecl || isa<VarDecl>(CurDecl))
-      CurDecl = getContext().getTranslationUnitDecl();
-
-    const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual();
-    std::string FunctionName;
-    if (isa<BlockDecl>(CurDecl)) {
-      // Blocks use the mangled function name.
-      // FIXME: ComputeName should handle blocks.
-      FunctionName = FnName.str();
-    } else if (isa<CapturedDecl>(CurDecl)) {
-      // For a captured statement, the function name is its enclosing
-      // function name not the one compiler generated.
-      FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
-    } else {
-      FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
-      assert(cast<ConstantArrayType>(E->getType())->getSize() - 1 ==
-                 FunctionName.size() &&
-             "Computed __func__ length differs from type!");
-    }
-
-    llvm::Constant *C;
-    if (ElemType->isWideCharType()) {
-      SmallString<32> RawChars;
-      ConvertUTF8ToWideString(
-          getContext().getTypeSizeInChars(ElemType).getQuantity(), FunctionName,
-          RawChars);
-      StringLiteral *SL = StringLiteral::Create(
-          getContext(), RawChars, StringLiteral::Wide,
-          /*Pascal = */ false, E->getType(), E->getLocation());
-      C = CGM.GetAddrOfConstantStringFromLiteral(SL);
-    } else {
-      C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1);
-    }
-    return MakeAddrLValue(C, E->getType());
-  }
-  }
+  assert(E->getStringLiteral() != nullptr &&
+         "No string literal is associated with PredefinedExpr");
+  return EmitStringLiteralLValue(E->getStringLiteral());
 }
 
 /// Emit a type description suitable for use by a runtime sanitizer library. The
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -423,6 +423,7 @@
   VisitExpr(E);
   E->setLocation(ReadSourceLocation(Record, Idx));
   E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+  E->setStringLiteral(cast<StringLiteral>(Reader.ReadSubExpr()));
 }
 
 void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -333,6 +333,7 @@
   VisitExpr(E);
   Writer.AddSourceLocation(E->getLocation(), Record);
   Record.push_back(E->getIdentType()); // FIXME: stable encoding
+  Writer.AddStmt(E->getStringLiteral());
   Code = serialization::EXPR_PREDEFINED;
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to