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