]> granicus.if.org Git - clang/commitdiff
Diagnose declarations that don't declare anything, and fix PR3020.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 28 Dec 2008 15:28:59 +0000 (15:28 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 28 Dec 2008 15:28:59 +0000 (15:28 +0000)
Examples:
int;
typedef int;

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

include/clang/Parse/DeclSpec.h
lib/Parse/DeclSpec.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/Parser/cxx-template-decl.cpp
test/Sema/decl-invalid.c
test/SemaCXX/class.cpp

index 8b2033bfbe0b26d44349eb7049e955aa7bc55c85..2fd00dd640142ec3f2cf73f2b56e4031543802b5 100644 (file)
@@ -318,6 +318,10 @@ public:
   /// things like "_Imaginary" (lacking an FP type).  After calling this method,
   /// DeclSpec is guaranteed self-consistent, even if an error occurred.
   void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang);
+
+  /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
+  /// without a Declarator. Only tag declspecs can stand alone.
+  bool isMissingDeclaratorOk();
 };
 
 /// ObjCDeclSpec - This class captures information about 
index b0ac36870ca65850a0348ac8cd90081afd38f978..258dc87c446bf3ebff92b3bc4615f6f55393c0ec 100644 (file)
@@ -313,3 +313,11 @@ void DeclSpec::Finish(Diagnostic &D, SourceManager& SrcMgr,
   // 'data definition has no type or storage class'?
 }
 
+bool DeclSpec::isMissingDeclaratorOk() {
+  TST tst = getTypeSpecType();
+  return (tst == TST_union
+       || tst == TST_struct
+       || tst == TST_class
+       || tst == TST_enum
+      ) && getTypeRep() != 0;
+}
index 3225628a9d85fe97b7a0cffb9baa7692ff69d55c..94e8a3ccccdb4db5516b305b0d86c86f08503d76 100644 (file)
@@ -302,7 +302,7 @@ public:
 
   /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
   /// no declarator (e.g. "struct foo;") is parsed.
-  virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);  
+  virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);
   
   virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                            SourceLocation KWLoc, const CXXScopeSpec &SS,
index 1f6cbc4f32ccfb06b6cea74346691d2852485d81..875f0f19ad98f1d47c706387ccf1daaca698d371 100644 (file)
@@ -773,10 +773,17 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
 /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
 /// no declarator (e.g. "struct foo;") is parsed.
 Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
-  // TODO: emit error on 'int;' or 'const enum foo;'.
-  // TODO: emit error on 'typedef int;'
-  // if (!DS.isMissingDeclaratorOk()) Diag(...);
-  
+  // FIXME: Isn't that more of a parser diagnostic than a sema diagnostic?
+  if (!DS.isMissingDeclaratorOk()) {
+    // FIXME: This diagnostic is emitted even when various previous
+    // errors occurred (see e.g. test/Sema/decl-invalid.c). However,
+    // DeclSpec has no means of communicating this information, and the
+    // responsible parser functions are quite far apart.
+    Diag(DS.getSourceRange().getBegin(), diag::err_no_declarators)
+      << DS.getSourceRange();
+    return 0;
+  }
+
   return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
 }
 
index 53813776e77edeadb8af9434514732abe73872c9..79b04cfc79773003e36f3f2ac6f45b864df63904 100644 (file)
@@ -5,10 +5,12 @@ export class foo { };   // expected-error {{expected template}}
 template  x;            // expected-error {{expected '<' after 'template'}}
 export template x;      // expected-error {{expected '<' after 'template'}} \
                         // expected-note {{exported templates are unsupported}}
-template < ;            // expected-error {{parse error}}
-template <template X> ; // expected-error {{expected '<' after 'template'}}
-template <template <typename> > ;       // expected-error {{expected 'class' before '>'}}
-template <template <typename> Foo> ;    // expected-error {{expected 'class' before 'Foo'}}
+// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic. This is
+// because ParseNonTypeTemplateParameter starts parsing a DeclSpec.
+template < ;            // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
+template <template X> struct Err1; // expected-error {{expected '<' after 'template'}}
+template <template <typename> > struct Err2;       // expected-error {{expected 'class' before '>'}}
+template <template <typename> Foo> struct Err3;    // expected-error {{expected 'class' before 'Foo'}}
 
 // Template function declarations
 template <typename T> void foo();
index 767d6e6ab40c8af17a31eced8cd873f8151c6b22..78a9ee1d4bfb1e96d26b7f962dfadb8d7856735f 100644 (file)
@@ -1,6 +1,7 @@
 // RUN: clang %s -fsyntax-only -verify
 
-typedef union <anonymous> __mbstate_t;  // expected-error {{declaration of anonymous union must be a definition}}
+// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic
+typedef union <anonymous> __mbstate_t;  // expected-error {{declaration of anonymous union must be a definition}} expected-error {{declaration does not declare anything}}
 
 
 // PR2017
@@ -9,3 +10,9 @@ int a() {
   int r[x()];  // expected-error {{size of array has non-integer type 'void'}}
 }
 
+int; // expected-error {{declaration does not declare anything}}
+typedef int; // expected-error {{declaration does not declare anything}}
+const int; // expected-error {{declaration does not declare anything}}
+struct; // expected-error {{declaration of anonymous struct must be a definition}} // expected-error {{declaration does not declare anything}}
+typedef int I;
+I; // expected-error {{declaration does not declare anything}}
index b7d1ca34dcfad799818f191c2ca87b3ce896a02d..7e06415a09da47df8c8f247730f89615844d8678 100644 (file)
@@ -100,4 +100,8 @@ mutable void gfn(); // expected-error {{illegal storage class on function}}
 void ogfn()
 {
   mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}}
+
+  // PR3020: This used to crash due to double ownership of C4.
+  struct C4;
+  C4; // expected-error {{declaration does not declare anything}}
 }