]> granicus.if.org Git - clang/commitdiff
Diagnose uses of function specifiers on declarations which don't declare
authorEli Friedman <eli.friedman@gmail.com>
Tue, 7 Apr 2009 19:37:57 +0000 (19:37 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 7 Apr 2009 19:37:57 +0000 (19:37 +0000)
functions.  Fixes PR3941.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68541 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/CodeGen/alias.c
test/Sema/inline.c [new file with mode: 0644]
test/SemaCXX/inline.cpp [new file with mode: 0644]

index ddb066e3d68c6229bea692d4209db73179942c5c..4dbd12dd9fd0e88e8f8d09a04d9115b5b575d384 100644 (file)
@@ -87,6 +87,8 @@ def err_declarator_need_ident : Error<"declarator requires an identifier">;
 def err_bad_language : Error<"unknown linkage language">;
 def warn_use_out_of_scope_declaration : Warning<
   "use of out-of-scope declaration of %0">;
+def err_inline_non_function : Error<
+  "'inline' can only appear on functions">;
 
 /// Built-in functions.
 def ext_implicit_lib_function_decl : ExtWarn<
@@ -254,6 +256,8 @@ def err_mutable_nonmember : Error<
   "'mutable' can only be applied to member variables">;
 def err_virtual_non_function : Error<
   "'virtual' can only appear on non-static member functions">;
+def err_explicit_non_function : Error<
+  "'virtual' can only appear on non-static member functions">;
 def err_virtual_out_of_class : Error<
   "'virtual' can only be specified inside the class definition">;
 def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
index 5582ac9f8646fb15908ffa568cb01cd3d0af7f0b..09ef84d4e2c76a9fb11897703d22ec9c25ae1039 100644 (file)
@@ -338,6 +338,7 @@ public:
   DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition);
   void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
                                         Scope *S);
+  void DiagnoseFunctionSpecifiers(Declarator& D);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     QualType R,
                                     Decl* PrevDecl, bool& InvalidDecl,
index 7cf44bf6acd12c98a15b2e7874d8235a057c4dce..54be9b4c3dfdad373e5c372e1160e312e5b284fc 100644 (file)
@@ -1478,6 +1478,24 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
   }
 }
 
+/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// does not identify a function.
+void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+  // FIXME: We should probably indicate the identifier in question to avoid
+  // confusion for constructs like "inline int a(), b;"
+  if (D.getDeclSpec().isInlineSpecified())
+    Diag(D.getDeclSpec().getInlineSpecLoc(), 
+         diag::err_inline_non_function);
+
+  if (D.getDeclSpec().isVirtualSpecified())
+    Diag(D.getDeclSpec().getVirtualSpecLoc(), 
+         diag::err_virtual_non_function);
+
+  if (D.getDeclSpec().isExplicitSpecified())
+    Diag(D.getDeclSpec().getExplicitSpecLoc(), 
+         diag::err_explicit_non_function);
+}
+
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                              QualType R, Decl* PrevDecl, bool& InvalidDecl, 
@@ -1494,12 +1512,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   if (getLangOptions().CPlusPlus) {
     // Check that there are no default arguments (C++ only).
     CheckExtraCXXDefaultArguments(D);
-
-    if (D.getDeclSpec().isVirtualSpecified())
-      Diag(D.getDeclSpec().getVirtualSpecLoc(), 
-           diag::err_virtual_non_function);
   }
 
+  DiagnoseFunctionSpecifiers(D);
+
   TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
   if (!NewTD) return 0;
 
@@ -1639,9 +1655,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     return 0;
   }
 
-  if (D.getDeclSpec().isVirtualSpecified())
-    Diag(D.getDeclSpec().getVirtualSpecLoc(), 
-         diag::err_virtual_non_function);
+  DiagnoseFunctionSpecifiers(D);
 
   bool ThreadSpecified = D.getDeclSpec().isThreadSpecified();
   if (!DC->isRecord() && S->getFnParent() == 0) {
@@ -2615,7 +2629,8 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
          diag::err_invalid_storage_class_in_func_decl);
     D.getMutableDeclSpec().ClearStorageClassSpecs();
   }
-  
+  DiagnoseFunctionSpecifiers(D);
+
   // Check that there are no default arguments inside the type of this
   // parameter (C++ only).
   if (getLangOptions().CPlusPlus)
@@ -3566,12 +3581,10 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
 
   if (getLangOptions().CPlusPlus) {
     CheckExtraCXXDefaultArguments(D);
-
-    if (D.getDeclSpec().isVirtualSpecified())
-      Diag(D.getDeclSpec().getVirtualSpecLoc(), 
-           diag::err_virtual_non_function);
   }
 
+  DiagnoseFunctionSpecifiers(D);
+
   NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true);
   if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
     PrevDecl = 0;
index c1a3baa929328323df580d96c095a94bb52b86ea..b0c71fbdfca44291bb2b3c23b7f09ed8ee058eec 100644 (file)
@@ -20,7 +20,7 @@ int foo() __attribute__((alias("foo1")));
 
 
 // RUN: grep '@bar1 = internal global i32 42' %t
-static inline int bar1 = 42;
+static int bar1 = 42;
 int bar() __attribute__((alias("bar1")));
 
 
diff --git a/test/Sema/inline.c b/test/Sema/inline.c
new file mode 100644 (file)
index 0000000..adcde51
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Check that we don't allow illegal uses of inline
+inline int a; // expected-error{{'inline' can only appear on functions}}
+typedef inline int b; // expected-error{{'inline' can only appear on functions}}
+int d(inline int a); // expected-error{{'inline' can only appear on functions}}
diff --git a/test/SemaCXX/inline.cpp b/test/SemaCXX/inline.cpp
new file mode 100644 (file)
index 0000000..7d0505a
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Check that we don't allow illegal uses of inline
+// (checking C++-only constructs here)
+struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}}