From: Chris Lattner Date: Sat, 12 Jan 2008 18:39:25 +0000 (+0000) Subject: Tighten up handling of __func__ and friends: it should be an array X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1423ea4146f0f71e027adbcd04c9e715711d8063;p=clang Tighten up handling of __func__ and friends: it should be an array of const char, and it should error if it occurs outside a function. Is it valid in an objc method? If so we should handle that too. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45910 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 88ee864b24..1e81d5c242 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -115,25 +115,23 @@ Sema::ExprResult Sema::ActOnPreDefinedExpr(SourceLocation Loc, PreDefinedExpr::IdentType IT; switch (Kind) { - default: - assert(0 && "Unknown simple primary expr!"); - case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] - IT = PreDefinedExpr::Func; - break; - case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] - IT = PreDefinedExpr::Function; - break; - case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] - IT = PreDefinedExpr::PrettyFunction; - break; + default: assert(0 && "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___PRETTY_FUNCTION__: IT = PreDefinedExpr::PrettyFunction; break; } + + // Verify that this is in a function context. + if (CurFunctionDecl == 0) + return Diag(Loc, diag::err_predef_outside_function); // Pre-defined identifiers are of type char[x], where x is the length of the // string. llvm::APSInt Length(32); Length = CurFunctionDecl->getIdentifier()->getLength() + 1; - QualType ResTy = Context.getConstantArrayType(Context.CharTy, Length, - ArrayType::Normal, 0); + + QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const); + ResTy = Context.getConstantArrayType(ResTy, Length, ArrayType::Normal, 0); return new PreDefinedExpr(Loc, ResTy, IT); } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index b91c7313f1..90a900a734 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -501,6 +501,9 @@ DIAG(warn_octal_escape_too_large, WARNING, DIAG(err_hex_escape_no_digits, ERROR, "\\x used with no following hex digits") + +DIAG(err_predef_outside_function, ERROR, + "predefined identifier is only valid inside function") // Declarations. DIAG(err_typename_requires_specqual, ERROR, diff --git a/test/Sema/predef.c b/test/Sema/predef.c index f3dae39c10..bd5e1a98b2 100644 --- a/test/Sema/predef.c +++ b/test/Sema/predef.c @@ -1,7 +1,12 @@ -// RUN: clang -fsyntax-only %s +// RUN: clang -fsyntax-only -verify %s -int abcdefghi12(void) { +void abcdefghi12(void) { const char (*ss)[12] = &__func__; - return sizeof(__func__); + static int arr[sizeof(__func__)==12 ? 1 : -1]; } +char *X = __func__; // expected-error {{predefined identifier is only valid}} + +void a() { + __func__[0] = 'a'; // expected-error {{variable is not assignable}} +}