]> granicus.if.org Git - clang/commitdiff
Fix a couple of bugs, add some new cool stuff.
authorChris Lattner <sabre@nondot.org>
Wed, 25 Jul 2007 00:24:17 +0000 (00:24 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 25 Jul 2007 00:24:17 +0000 (00:24 +0000)
1. Fix a todo in Parser::ParseTag, to recover better.  On code like
   that in test/Sema/decl-invalid.c it causes us to return a single
   error instead of multiple.
2. Fix an error in Sema::ParseDeclarator, where it would crash if the
   declarator didn't have an identifier.  Instead, diagnose the problem.
3. Start adding infrastructure to track the range of locations covered
   by a declspec or declarator.  This is mostly implemented for declspec,
   but could be improved, it is missing for declarator.

Thanks to Neil for pointing out this crash.

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

Parse/DeclSpec.cpp
Parse/ParseDecl.cpp
Sema/SemaDecl.cpp
include/clang/Basic/DiagnosticKinds.def
include/clang/Basic/SourceLocation.h
include/clang/Parse/DeclSpec.h
test/Sema/decl-invalid.c [new file with mode: 0644]

index 117ff12e597f424421d7849df5aab5cc1a651f57..d3ddf47a837cbf16d653bcd6682fc4962b3457e3 100644 (file)
@@ -277,7 +277,6 @@ void DeclSpec::Finish(Diagnostic &D, const LangOptions &Lang) {
   }
 
   // Okay, now we can infer the real type.
-  // TODO: infer real type.
   
   // TODO: return "auto function" and other bad things based on the real type.
   
index c40e7496592643cd9db44499f239f2f3d4be39b2..b05fd7898d08807de09f0644339be504199aebba 100644 (file)
@@ -296,7 +296,6 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
 void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
   /// specifier-qualifier-list is a subset of declaration-specifiers.  Just
   /// parse declaration-specifiers and complain about extra stuff.
-  SourceLocation Loc = Tok.getLocation();
   ParseDeclarationSpecifiers(DS);
   
   // Validate declspec for type-name.
@@ -367,6 +366,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
 /// [C99]   'inline'
 ///
 void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
+  DS.Range.setBegin(Tok.getLocation());
   while (1) {
     int isInvalid = false;
     const char *PrevSpec = 0;
@@ -509,6 +509,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
       else                 // extwarn.
         Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
     }
+    DS.Range.setEnd(Tok.getLocation());
     ConsumeToken();
   }
 }
@@ -527,7 +528,9 @@ bool Parser::ParseTag(DeclTy *&Decl, unsigned TagType, SourceLocation StartLoc){
   if (Tok.getKind() != tok::identifier &&
       Tok.getKind() != tok::l_brace) {
     Diag(Tok, diag::err_expected_ident_lbrace);
-    // TODO: better error recovery here.
+    
+    // Skip the rest of this declarator, up until the comma or semicolon.
+    SkipUntil(tok::comma, true);
     return true;
   }
   
index c546df27cc8cf661f610e9c1b2e062f3c7e2c693..3053d2e2a8a1ba1a377131c8b3fed2de1ead3c17 100644 (file)
@@ -278,6 +278,14 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
   Expr *Init = static_cast<Expr*>(init);
   IdentifierInfo *II = D.getIdentifier();
   
+  // All of these full declarators require an identifier.  If it doesn't have
+  // one, the ParsedFreeStandingDeclSpec action should be used.
+  if (II == 0) {
+    Diag(D.getDeclSpec().getSourceRange().Begin(), diag::err_declarator_need_ident,
+         D.getDeclSpec().getSourceRange(), D.getSourceRange());
+    return 0;
+  }
+  
   // See if this is a redefinition of a variable in the same scope.
   Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
                                     D.getIdentifierLoc(), S);
index 4069bda64538c04eac855e15513c75e0af485883..64de3aa16edf79766e76fabc77f01b3c382b8508 100644 (file)
@@ -427,6 +427,8 @@ DIAG(err_invalid_storage_class_in_func_decl, ERROR,
      "invalid storage class specifier in function declarator")
 DIAG(err_invalid_reference_qualifier_application, ERROR,
      "'%0' qualifier may not be applied to a reference")
+DIAG(err_declarator_need_ident, ERROR,
+     "declarator requires an identifier")
 
 // Attributes
 DIAG(err_attribute_wrong_number_arguments, ERROR,
index 6ba17b053089d90e00ec3cb1e12ba55da56ee0fb..2ebed47b72c2916734de3489ccfc1fc39a3ae6ec 100644 (file)
@@ -161,6 +161,9 @@ public:
   SourceLocation Begin() const { return B; }
   SourceLocation End() const { return E; }
   
+  void setBegin(SourceLocation b) { B = b; }
+  void setEnd(SourceLocation e) { E = e; }
+  
   bool isValid() const { return B.isValid() && E.isValid(); }
 };
   
index 95be99383102a491c636bf26a6a17f2ebd89b96e..7c5fb1a00b318c9543ead29e20eec7fbd16776c5 100644 (file)
@@ -28,6 +28,9 @@ namespace clang {
 /// and function-specifiers.
 class DeclSpec {
 public:
+  SourceRange Range;
+  const SourceRange &getSourceRange() const { return Range; }
+  
   // storage-class-specifier
   enum SCS {
     SCS_unspecified,
@@ -414,8 +417,8 @@ struct DeclaratorChunk {
 /// Abstract declarators are used when parsing types, and don't have an
 /// identifier.  Normal declarators do have ID's.
 ///
-/// This is NOT intended to be a small value object: this should be a transient
-/// object that lives on the stack.
+/// Instances of this class should be a transient object that lives on the
+/// stack, not objects that are allocated in large quantities on the heap.
 class Declarator {
   const DeclSpec &DS;
   IdentifierInfo *Identifier;
@@ -459,6 +462,9 @@ public:
   
   TheContext getContext() const { return Context; }
   
+  // getSourceRange - FIXME: This should be implemented.
+  const SourceRange getSourceRange() const { return SourceRange(); }
+  
   /// clear - Reset the contents of this Declarator.
   void clear() {
     Identifier = 0;
diff --git a/test/Sema/decl-invalid.c b/test/Sema/decl-invalid.c
new file mode 100644 (file)
index 0000000..dda6601
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: clang %s -parse-ast-check
+
+typedef union <anonymous> __mbstate_t;  // expected-error: {{expected identifier or}}