]> granicus.if.org Git - clang/commitdiff
Tighten up handling of __func__ and friends: it should be an array
authorChris Lattner <sabre@nondot.org>
Sat, 12 Jan 2008 18:39:25 +0000 (18:39 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 12 Jan 2008 18:39:25 +0000 (18:39 +0000)
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

Sema/SemaExpr.cpp
include/clang/Basic/DiagnosticKinds.def
test/Sema/predef.c

index 88ee864b24ec88ed292ab83e813f3f867ba05195..1e81d5c24290b2fbd0b5dbfdd97cead5799b8bd2 100644 (file)
@@ -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);
 }
 
index b91c7313f18766e62b7fdb2859b5fe795b2129d3..90a900a734b56c6e70f4784a1771270239758722 100644 (file)
@@ -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,
index f3dae39c1015abcc37867103bf164792f9052610..bd5e1a98b24bd9cd2b9fa8a716698cfa58e43b00 100644 (file)
@@ -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}}
+}