aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/DeclSpec.h4
-rw-r--r--lib/Parse/DeclSpec.cpp8
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDecl.cpp15
-rw-r--r--test/Parser/cxx-template-decl.cpp10
-rw-r--r--test/Sema/decl-invalid.c9
-rw-r--r--test/SemaCXX/class.cpp4
7 files changed, 42 insertions, 10 deletions
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 8b2033bfbe..2fd00dd640 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -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
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index b0ac36870c..258dc87c44 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -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;
+}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3225628a9d..94e8a3cccc 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1f6cbc4f32..875f0f19ad 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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()));
}
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index 53813776e7..79b04cfc79 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -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();
diff --git a/test/Sema/decl-invalid.c b/test/Sema/decl-invalid.c
index 767d6e6ab4..78a9ee1d4b 100644
--- a/test/Sema/decl-invalid.c
+++ b/test/Sema/decl-invalid.c
@@ -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}}
diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp
index b7d1ca34dc..7e06415a09 100644
--- a/test/SemaCXX/class.cpp
+++ b/test/SemaCXX/class.cpp
@@ -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}}
}