summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaExpr.cpp41
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp20
-rw-r--r--test/CodeGenCXX/predefined-expr.cpp22
-rw-r--r--test/SemaCXX/predefined-expr.cpp38
5 files changed, 86 insertions, 37 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index d6ce4d932e..ad27b3fd3f 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3236,6 +3236,8 @@ public:
SourceLocation LitEndLoc,
TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
+ ExprResult BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT);
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4e2e24eab4..10d384b8d8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2745,22 +2745,10 @@ ExprResult Sema::BuildDeclarationNameExpr(
}
}
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
- PredefinedExpr::IdentType IT;
-
- switch (Kind) {
- default: llvm_unreachable("Unknown simple primary expr!");
- case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
- case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
- case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
- case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
- }
-
- // Pre-defined identifiers are of type char[x], where x is the length of the
- // string.
-
- // Pick the current block, lambda or function.
- Decl *currentDecl;
+ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT) {
+ // Pick the current block, lambda, captured statement or function.
+ Decl *currentDecl = 0;
if (const BlockScopeInfo *BSI = getCurBlock())
currentDecl = BSI->TheDecl;
else if (const LambdaScopeInfo *LSI = getCurLambda())
@@ -2776,9 +2764,11 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
}
QualType ResTy;
- if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+ if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
- } else {
+ else {
+ // Pre-defined identifiers are of type char[x], where x is the length of
+ // the string.
unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
@@ -2788,9 +2778,24 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
+
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
}
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
+ PredefinedExpr::IdentType IT;
+
+ switch (Kind) {
+ default: llvm_unreachable("Unknown simple primary expr!");
+ case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+ case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
+ case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+ }
+
+ return BuildPredefinedExpr(Loc, IT);
+}
+
ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
SmallString<16> CharBuffer;
bool Invalid = false;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 9b7b4a8596..dd10cbe2b7 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1149,25 +1149,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return SemaRef.Owned(E);
- FunctionDecl *currentDecl = getSema().getCurFunctionDecl();
- assert(currentDecl && "Must have current function declaration when "
- "instantiating.");
-
- PredefinedExpr::IdentType IT = E->getIdentType();
-
- unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
-
- llvm::APInt LengthI(32, Length + 1);
- QualType ResTy;
- if (IT == PredefinedExpr::LFunction)
- ResTy = getSema().Context.WideCharTy.withConst();
- else
- ResTy = getSema().Context.CharTy.withConst();
- ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI,
- ArrayType::Normal, 0);
- PredefinedExpr *PE =
- new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT);
- return getSema().Owned(PE);
+ return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType());
}
ExprResult
diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp
index 24ead8f8f4..9062ee095c 100644
--- a/test/CodeGenCXX/predefined-expr.cpp
+++ b/test/CodeGenCXX/predefined-expr.cpp
@@ -9,6 +9,8 @@
// CHECK: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00"
// CHECK: private unnamed_addr constant [122 x i8] c"static void ClassWithTemplateTemplateParam<char, NS::ClassTemplate>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
// CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00"
+// CHECK: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00"
+// CHECK: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::<anonymous class>::operator()() const\00"
// CHECK: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00"
// CHECK: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00"
@@ -376,6 +378,23 @@ void functionTemplateWithUnnamedTemplateParameter(T t)
}
template <typename T>
+void functionTemplateWithLambda(T t)
+{
+ []() {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ } ();
+}
+
+template <typename T>
+void functionTemplateWithCapturedStmt(T t)
+{
+ #pragma clang __debug captured
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+}
+
+template <typename T>
class OuterClass
{
public:
@@ -500,6 +519,9 @@ int main() {
functionTemplateExplicitSpecialization(0.0);
functionTemplateWithUnnamedTemplateParameter<int, float>(0.0f);
+ functionTemplateWithLambda<int>(0);
+ functionTemplateWithCapturedStmt<int>(0);
+
OuterClass<int *>::MiddleClass::InnerClass<float> omi;
omi.memberFunction(0, 0.0f);
diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp
index e203dd4be8..257d44c600 100644
--- a/test/SemaCXX/predefined-expr.cpp
+++ b/test/SemaCXX/predefined-expr.cpp
@@ -16,6 +16,40 @@ auto bar() -> decltype(42) {
return 0;
}
+// Within templates.
+template <typename T>
+int baz() {
+ static_assert(sizeof(__func__) == 4, "baz");
+ static_assert(sizeof(__FUNCTION__) == 4, "baz");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]");
+
+ []() {
+ static_assert(sizeof(__func__) == 11, "operator()");
+ static_assert(sizeof(__FUNCTION__) == 11, "operator()");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 50,
+ "auto baz()::<anonymous class>::operator()() const");
+ return 0;
+ }
+ ();
+
+ ^{
+ // FIXME: This is obviously wrong.
+ static_assert(sizeof(__func__) == 1, "__baz_block_invoke");
+ static_assert(sizeof(__FUNCTION__) == 1, "__baz_block_invoke");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__baz_block_invoke");
+ }
+ ();
+
+ #pragma clang __debug captured
+ {
+ static_assert(sizeof(__func__) == 4, "baz");
+ static_assert(sizeof(__FUNCTION__) == 4, "baz");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]");
+ }
+
+ return 0;
+}
+
int main() {
static_assert(sizeof(__func__) == 5, "main");
static_assert(sizeof(__FUNCTION__) == 5, "main");
@@ -62,4 +96,8 @@ int main() {
}
}
();
+
+ baz<int>();
+
+ return 0;
}