]> granicus.if.org Git - clang/commitdiff
This is a pretty big cleanup for how invalid decl/type are handle.
authorChris Lattner <sabre@nondot.org>
Sat, 25 Apr 2009 08:06:05 +0000 (08:06 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 25 Apr 2009 08:06:05 +0000 (08:06 +0000)
This gets rid of a bunch of random InvalidDecl bools in sema, changing
us to use the following approach:

1. When analyzing a declspec or declarator, if an error is found, we
   set a bit in Declarator saying that it is invalid.
2. Once the Decl is created by sema, we immediately set the isInvalid
   bit on it from what is in the declarator.  From this point on, sema
   consistently looks at and sets the bit on the decl.

This gives a very clear separation of concerns and simplifies a bunch
of code.  In addition to this, this patch makes these changes:

1. it renames DeclSpec::getInvalidType() -> isInvalidType().
2. various "merge" functions no longer return bools: they just set the
   invalid bit on the dest decl if invalid.
3. The ActOnTypedefDeclarator/ActOnFunctionDeclarator/ActOnVariableDeclarator
   methods now set invalid on the decl returned instead of returning an
   invalid bit byref.
4. In SemaType, refering to a typedef that was invalid now propagates the
   bit into the resultant type.  Stuff declared with the invalid typedef
   will now be marked invalid.
5. Various methods like CheckVariableDeclaration now return void and set the
   invalid bit on the decl they check.

There are a few minor changes to tests with this, but the only major bad
result is test/SemaCXX/constructor-recovery.cpp.  I'll take a look at this
next.

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

14 files changed:
include/clang/Parse/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaType.cpp
test/Sema/invalid-decl.c
test/Sema/tentative-decls.c
test/SemaCXX/constructor-recovery.cpp
test/SemaCXX/destructor.cpp

index 1be687be8efe6934ff50c44aa3123485d412b35e..e1f52a02466cdbd65b44c4b62e7cb2c1b848a1a2 100644 (file)
@@ -1017,8 +1017,8 @@ public:
 
   OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
 
-  void setInvalidType(bool flag) { InvalidType = flag; }
-  bool getInvalidType() const { 
+  void setInvalidType(bool Val = true) { InvalidType = Val; }
+  bool isInvalidType() const { 
     return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; 
   }
 
index 826845243084a31cef67d7e45ea083a39b9fef38..f02b8a068255d6717ce0fd4df8b2fc771c89d84f 100644 (file)
@@ -37,7 +37,7 @@ Action::TypeResult Parser::ParseTypeName() {
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   ParseDeclarator(DeclaratorInfo);
   
-  if (DeclaratorInfo.getInvalidType())
+  if (DeclaratorInfo.isInvalidType())
     return true;
 
   return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
index ec36fedc2d21bc2f153109ab4f4c84c5379f5a7a..55bc1862f56f5f1abbddfb6bb83ceac1ee6ecaf5 100644 (file)
@@ -1338,7 +1338,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
     SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
     ParamInfo.SetIdentifier(0, CaretLoc);
     ParamInfo.SetRangeEnd(Tmp);
-    if (ParamInfo.getInvalidType()) {
+    if (ParamInfo.isInvalidType()) {
       // If there was an error parsing the arguments, they may have
       // tried to use ^(x+y) which requires an argument list.  Just
       // skip the whole block literal.
index f00edddffe5ce2fcf8fc2c7d775045ea817d8aaa..2f1b9c84d2994f9614910e4c34d7222150e6a329 100644 (file)
@@ -860,7 +860,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
     }
     ParenTypeId = false;
   }
-  if (DeclaratorInfo.getInvalidType()) {
+  if (DeclaratorInfo.isInvalidType()) {
     SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
     return ExprError();
   }
@@ -938,7 +938,7 @@ bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
     ParseSpecifierQualifierList(D.getMutableDeclSpec());
     D.SetSourceRange(D.getDeclSpec().getSourceRange());
     ParseDeclarator(D);
-    return D.getInvalidType();
+    return D.isInvalidType();
   }
 
   // It's not a type, it has to be an expression list.
index 7426965a442062d3a1ab3c21e564d51bffdba576..984576b5af29524df4e0d6d1487fc9aeac03d821 100644 (file)
@@ -326,7 +326,8 @@ public:
   // Type Analysis / Processing: SemaType.cpp.
   //
   QualType adjustParameterType(QualType T);
-  QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc);
+  QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
+                                 bool &IsInvalid);
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
   QualType BuildPointerType(QualType T, unsigned Quals, 
                             SourceLocation Loc, DeclarationName Entity);
@@ -377,20 +378,18 @@ public:
                                         Scope *S);
   void DiagnoseFunctionSpecifiers(Declarator& D);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                                    QualType R,
-                                    Decl* PrevDecl, bool& InvalidDecl,
+                                    QualType R, Decl* PrevDecl,
                                     bool &Redeclaration);
   NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                                     QualType R, 
-                                     NamedDecl* PrevDecl, bool& InvalidDecl,
+                                     QualType R, NamedDecl* PrevDecl,
                                      bool &Redeclaration);
-  bool CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+  void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
                                 bool &Redeclaration);
   NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      QualType R, NamedDecl* PrevDecl, 
                                      bool IsFunctionDefinition,
-                                     bool& InvalidDecl, bool &Redeclaration);
-  bool CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+                                     bool &Redeclaration);
+  void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
                                 bool &Redeclaration, 
                                 bool &OverloadableAttrRequired);
   virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
@@ -518,10 +517,10 @@ public:
 
   /// Subroutines of ActOnDeclarator().
   TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
-  bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
+  void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
-  bool MergeVarDecl(VarDecl *New, Decl *Old);
+  void MergeVarDecl(VarDecl *New, Decl *Old);
   bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
 
   /// C++ Overloading.
index 9930dbc19bb5c0f3a0a02c674055614019ad570a..64c85a2aad16704a306a867d8e8fbae8809830f5 100644 (file)
@@ -471,11 +471,16 @@ NamespaceDecl *Sema::GetStdNamespace() {
 /// MergeTypeDefDecl - We just parsed a typedef 'New' which has the
 /// same name and scope as a previous declaration 'Old'.  Figure out
 /// how to resolve this situation, merging decls or emitting
-/// diagnostics as appropriate. Returns true if there was an error,
-/// false otherwise.
+/// diagnostics as appropriate. If there was an error, set New to be invalid.
 ///
-bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
+  // If either decl is known invalid already, set the new one to be invalid and
+  // don't bother doing any merging checks.
+  if (New->isInvalidDecl() || OldD->isInvalidDecl())
+    return New->setInvalidDecl();
+  
   bool objc_types = false;
+  
   // Allow multiple definitions for ObjC built-in typedefs.
   // FIXME: Verify the underlying types are equivalent!
   if (getLangOptions().ObjC1) {
@@ -492,20 +497,17 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
       if (!TypeID->isStr("Class"))
         break;
       Context.setObjCClassType(Context.getTypeDeclType(New));
-      objc_types = true;
-      return false;
+      return;
     case 3:
       if (!TypeID->isStr("SEL"))
         break;
       Context.setObjCSelType(Context.getTypeDeclType(New));
-      objc_types = true;
-      return false;
+      return;
     case 8:
       if (!TypeID->isStr("Protocol"))
         break;
       Context.setObjCProtoType(New->getUnderlyingType());
-      objc_types = true;
-      return false;
+      return;
     }
     // Fall through - the typedef name was not a builtin type.
   }
@@ -514,9 +516,9 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
   if (!Old) {
     Diag(New->getLocation(), diag::err_redefinition_different_kind) 
       << New->getDeclName();
-    if (!objc_types)
+    if (OldD->getLocation().isValid())
       Diag(OldD->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
 
   // Determine the "old" type we'll use for checking and diagnostics.  
@@ -534,12 +536,13 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
       Context.getCanonicalType(New->getUnderlyingType())) {
     Diag(New->getLocation(), diag::err_redefinition_different_typedef)
       << New->getUnderlyingType() << OldType;
-    if (!objc_types)
+    if (Old->getLocation().isValid())
       Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
-  if (objc_types) return false;
-  if (getLangOptions().Microsoft) return false;
+  
+  if (objc_types || getLangOptions().Microsoft)
+    return;
 
   // C++ [dcl.typedef]p2:
   //   In a given non-class scope, a typedef specifier can be used to
@@ -547,11 +550,11 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
   //   to the type to which it already refers.
   if (getLangOptions().CPlusPlus) {
     if (!isa<CXXRecordDecl>(CurContext))
-      return false;
+      return;
     Diag(New->getLocation(), diag::err_redefinition)
       << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
 
   // If we have a redefinition of a typedef in C, emit a warning.  This warning
@@ -560,7 +563,7 @@ bool Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
   Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
     << New->getDeclName();
   Diag(Old->getLocation(), diag::note_previous_definition);
-  return false;
+  return;
 }
 
 /// DeclhasAttr - returns true if decl Declaration already has the target
@@ -883,14 +886,19 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
 /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative 
 /// definitions here, since the initializer hasn't been attached.
 /// 
-bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
+  // If either decl is invalid, make sure the new one is marked invalid and
+  // don't do any other checking.
+  if (New->isInvalidDecl() || OldD->isInvalidDecl())
+    return New->setInvalidDecl();
+  
   // Verify the old decl was also a variable.
   VarDecl *Old = dyn_cast<VarDecl>(OldD);
   if (!Old) {
     Diag(New->getLocation(), diag::err_redefinition_different_kind)
       << New->getDeclName();
     Diag(OldD->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
 
   MergeAttributes(New, Old, Context);
@@ -901,7 +909,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
     Diag(New->getLocation(), diag::err_redefinition_different_type) 
       << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
   New->setType(MergedT);
 
@@ -910,7 +918,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
       (Old->getStorageClass() == VarDecl::None || Old->hasExternalStorage())) {
     Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
   // C99 6.2.2p4: 
   //   For an identifier declared with the storage-class specifier
@@ -927,7 +935,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
            Old->getStorageClass() == VarDecl::Static) {
     Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
 
   // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
@@ -940,7 +948,7 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
         !New->getLexicalDeclContext()->isRecord())) {
     Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return true;
+    return New->setInvalidDecl();
   }
 
   if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
@@ -953,8 +961,6 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
 
   // Keep a chain of previous declarations.
   New->setPreviousDeclaration(Old);
-
-  return false;
 }
 
 /// CheckParmsForFunctionDef - Check that the parameters of the given
@@ -1337,7 +1343,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
   // All of these full declarators require an identifier.  If it doesn't have
   // one, the ParsedFreeStandingDeclSpec action should be used.
   if (!Name) {
-    if (!D.getInvalidType())  // Reject this if we think it is valid.
+    if (!D.isInvalidType())  // Reject this if we think it is valid.
       Diag(D.getDeclSpec().getSourceRange().getBegin(),
            diag::err_declarator_need_ident)
         << D.getDeclSpec().getSourceRange() << D.getSourceRange();
@@ -1353,11 +1359,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
   DeclContext *DC;
   NamedDecl *PrevDecl;
   NamedDecl *New;
-  bool InvalidDecl = false;
 
   QualType R = GetTypeForDeclarator(D, S);
   if (R.isNull()) {
-    InvalidDecl = true;
+    D.setInvalidType();
     R = Context.IntTy;
     if (IsFunctionDefinition) // int(...)
       R = Context.getFunctionType(R, 0, 0, true, 0);
@@ -1368,7 +1373,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
   if (D.getCXXScopeSpec().isInvalid()) {
     DC = CurContext;
     PrevDecl = 0;
-    InvalidDecl = true;
+    D.setInvalidType();
   } else if (!D.getCXXScopeSpec().isSet()) {
     LookupNameKind NameKind = LookupOrdinaryName;
 
@@ -1430,14 +1435,16 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
       else 
         Diag(L, diag::err_invalid_declarator_scope)
           << Name << cast<NamedDecl>(DC) << R;
-      InvalidDecl = true;
+      D.setInvalidType();
     }
   }
 
   if (PrevDecl && PrevDecl->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
-    InvalidDecl = InvalidDecl 
-      || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+    if (!D.isInvalidType()) 
+      if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl))
+        D.setInvalidType();
+    
     // Just pretend that we didn't see the previous declaration.
     PrevDecl = 0;
   }
@@ -1452,15 +1459,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
 
   bool Redeclaration = false;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
-    New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl,
-                                 InvalidDecl, Redeclaration);
+    New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
   } else if (R->isFunctionType()) {
     New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl, 
-                                  IsFunctionDefinition, InvalidDecl,
-                                  Redeclaration);
+                                  IsFunctionDefinition, Redeclaration);
   } else {
-    New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, 
-                                  InvalidDecl, Redeclaration);
+    New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
   }
 
   if (New == 0)
@@ -1468,11 +1472,8 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
   
   // If this has an identifier and is not an invalid redeclaration,
   // add it to the scope stack.
-  if (Name && !(Redeclaration && InvalidDecl))
+  if (Name && !(Redeclaration && New->isInvalidDecl()))
     PushOnScopeChains(New, S);
-  // If any semantic error occurred, mark the decl as invalid.
-  if (D.getInvalidType() || InvalidDecl)
-    New->setInvalidDecl();
   
   return DeclPtrTy::make(New);
 }
@@ -1568,13 +1569,12 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
 
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                             QualType R, Decl* PrevDecl, bool& InvalidDecl, 
-                             bool &Redeclaration) {
+                             QualType R, Decl* PrevDecl, bool &Redeclaration) {
   // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
   if (D.getCXXScopeSpec().isSet()) {
     Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
       << D.getCXXScopeSpec().getRange();
-    InvalidDecl = true;
+    D.setInvalidType();
     // Pretend we didn't see the scope specifier.
     DC = 0;
   }
@@ -1591,6 +1591,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 
   TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
   if (!NewTD) return 0;
+  
+  if (D.isInvalidType())
+    NewTD->setInvalidDecl();
 
   // Handle attributes prior to checking for duplicates in MergeVarDecl
   ProcessDeclAttributes(NewTD, D);
@@ -1598,8 +1601,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // in an outer scope, it isn't the same thing.
   if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
     Redeclaration = true;
-    if (MergeTypeDefDecl(NewTD, PrevDecl))
-      InvalidDecl = true;
+    MergeTypeDefDecl(NewTD, PrevDecl);
   }
 
   // C99 6.7.7p2: If a typedef name specifies a variably modified type
@@ -1622,7 +1624,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
           Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
         else
           Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
-        InvalidDecl = true;
+        NewTD->setInvalidDecl();
       }
     }
   }
@@ -1696,7 +1698,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
 
 NamedDecl*
 Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
-                              QualType R,NamedDecl* PrevDecl, bool& InvalidDecl,
+                              QualType R,NamedDecl* PrevDecl,
                               bool &Redeclaration) {
   DeclarationName Name = GetNameForDeclarator(D);
 
@@ -1718,7 +1720,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     // mutable can only appear on non-static class members, so it's always
     // an error here
     Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
-    InvalidDecl = true;
+    D.setInvalidType();
     SC = VarDecl::None;
     break;
   }
@@ -1737,7 +1739,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     // appear in the declaration specifiers in an external declaration.
     if (SC == VarDecl::Auto || SC == VarDecl::Register) {
       Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
-      InvalidDecl = true;
+      D.setInvalidType();
     }
   }
   if (DC->isRecord() && !CurContext->isRecord()) {
@@ -1757,6 +1759,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                           // FIXME: Move to DeclGroup...
                           D.getDeclSpec().getSourceRange().getBegin());
 
+  if (D.isInvalidType())
+    NewVD->setInvalidDecl();
+  
   if (D.getDeclSpec().isThreadSpecified()) {
     if (NewVD->hasLocalStorage())
       Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@@ -1797,22 +1802,21 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
       Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
         << D.getCXXScopeSpec().getRange();
       PrevDecl = 0;
-      InvalidDecl = true;
+      NewVD->setInvalidDecl();
     }
   } else if (D.getCXXScopeSpec().isSet()) {
     // No previous declaration in the qualifying scope.
     Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
       << Name << D.getCXXScopeSpec().getRange();
-    InvalidDecl = true;
+    NewVD->setInvalidDecl();
   }
 
-  if (CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration))
-    InvalidDecl = true;
+  CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
 
   // If this is a locally-scoped extern C variable, update the map of
   // such variables.
   if (CurContext->isFunctionOrMethod() && NewVD->isExternC(Context) &&
-      !InvalidDecl)
+      !NewVD->isInvalidDecl())
     RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S);
 
   return NewVD;
@@ -1826,23 +1830,25 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 /// check variables after they have been parsed and their declarators
 /// have been translated into a declaration, and to check 
 ///
-/// \returns true if an error was encountered, false otherwise.
-bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
                                     bool &Redeclaration) {
-  bool Invalid = false;
-
+  // If the decl is already known invalid, don't check it.
+  if (NewVD->isInvalidDecl())
+    return;
+  
   QualType T = NewVD->getType();
 
   if (T->isObjCInterfaceType()) {
     Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
-    Invalid = true;
+    return NewVD->setInvalidDecl();
   }
   
   // The variable can not have an abstract class type.
   if (RequireNonAbstractType(NewVD->getLocation(), T,
                              diag::err_abstract_type_in_decl, 
                              AbstractVariableType))
-    Invalid = true;
+    return NewVD->setInvalidDecl();
 
   // Emit an error if an address space was applied to decl with local storage.
   // This includes arrays of objects with address space qualifiers, but not
@@ -1850,7 +1856,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
   // ISO/IEC TR 18037 S5.1.2
   if (NewVD->hasLocalStorage() && (T.getAddressSpace() != 0)) {
     Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
-    Invalid = true;
+    return NewVD->setInvalidDecl();
   }
 
   if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
@@ -1866,34 +1872,35 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
     bool SizeIsNegative;
     QualType FixedTy =
         TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
-    if (!FixedTy.isNull()) {
-      Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
-      NewVD->setType(FixedTy);
-    } else if (T->isVariableArrayType()) {
-      Invalid = true;
-
+    
+    if (FixedTy.isNull() && T->isVariableArrayType()) {
       const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
       // FIXME: This won't give the correct result for 
       // int a[10][n];      
       SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
-
+      
       if (NewVD->isFileVarDecl())
         Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
-          << SizeRange;
+        << SizeRange;
       else if (NewVD->getStorageClass() == VarDecl::Static)
         Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
-          << SizeRange;
+        << SizeRange;
       else
         Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
-            << SizeRange;
-    } else {
-      Invalid = true;
-      
+        << SizeRange;
+      return NewVD->setInvalidDecl();
+    } 
+    
+    if (FixedTy.isNull()) {
       if (NewVD->isFileVarDecl())
         Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
       else
         Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
+      return NewVD->setInvalidDecl();
     }
+    
+    Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+    NewVD->setType(FixedTy);
   }
 
   if (!PrevDecl && NewVD->isExternC(Context)) {
@@ -1906,26 +1913,22 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
       PrevDecl = Pos->second;
   }
 
-  if (!Invalid && T->isVoidType() && !NewVD->hasExternalStorage()) {
+  if (T->isVoidType() && !NewVD->hasExternalStorage()) {
     Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
       << T;
-    Invalid = true;
+    return NewVD->setInvalidDecl();
   }
 
   if (PrevDecl) {
     Redeclaration = true;
-    if (MergeVarDecl(NewVD, PrevDecl))
-      Invalid = true;
+    MergeVarDecl(NewVD, PrevDecl);
   }
-
-  return NewVD->isInvalidDecl() || Invalid;
 }
 
 NamedDecl* 
 Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                               QualType R, NamedDecl* PrevDecl,
-                              bool IsFunctionDefinition,
-                              bool &InvalidDecl, bool &Redeclaration) {
+                              bool IsFunctionDefinition, bool &Redeclaration) {
   assert(R.getTypePtr()->isFunctionType());
 
   DeclarationName Name = GetNameForDeclarator(D);
@@ -1937,7 +1940,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   case DeclSpec::SCS_mutable:
     Diag(D.getDeclSpec().getStorageClassSpecLoc(), 
          diag::err_typecheck_sclass_func);
-    InvalidDecl = true;
+    D.setInvalidType();
     break;
   case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
   case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
@@ -1973,14 +1976,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                              R->getAsFunctionType()->getResultType(),
                              diag::err_abstract_type_in_decl, 
                              AbstractReturnType))
-    InvalidDecl = true;
+    D.setInvalidType();
   
   // Do not allow returning a objc interface by-value.
   if (R->getAsFunctionType()->getResultType()->isObjCInterfaceType()) {
     Diag(D.getIdentifierLoc(),
          diag::err_object_cannot_be_passed_returned_by_value) << 0
       << R->getAsFunctionType()->getResultType();
-    InvalidDecl = true;
+    D.setInvalidType();
   }
   
   bool isVirtualOkay = false;
@@ -1990,7 +1993,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     assert(DC->isRecord() &&
            "Constructors can only be declared in a member context");
 
-    InvalidDecl = InvalidDecl || CheckConstructorDeclarator(D, R, SC);
+    if (!D.isInvalidType())
+      D.setInvalidType(CheckConstructorDeclarator(D, R, SC));
 
     // Create the new declaration
     NewFD = CXXConstructorDecl::Create(Context, 
@@ -2001,8 +2005,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   } else if (D.getKind() == Declarator::DK_Destructor) {
     // This is a C++ destructor declaration.
     if (DC->isRecord()) {
-      InvalidDecl = InvalidDecl || CheckDestructorDeclarator(D, R, SC);
-
+      if (!D.isInvalidType())
+        D.setInvalidType(CheckDestructorDeclarator(D, R, SC));
+      
       NewFD = CXXDestructorDecl::Create(Context,
                                         cast<CXXRecordDecl>(DC),
                                         D.getIdentifierLoc(), Name, R, 
@@ -2020,7 +2025,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                    /*hasPrototype=*/true,
                                    // FIXME: Move to DeclGroup...
                                    D.getDeclSpec().getSourceRange().getBegin());
-      InvalidDecl = true;
+      D.setInvalidType();
     }
   } else if (D.getKind() == Declarator::DK_Conversion) {
     if (!DC->isRecord()) {
@@ -2028,7 +2033,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
            diag::err_conv_function_not_member);
       return 0;
     } else {
-      InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
+      if (!D.isInvalidType())
+        D.setInvalidType(CheckConversionDeclarator(D, R, SC));
 
       NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                         D.getIdentifierLoc(), Name, R,
@@ -2062,7 +2068,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                  D.getDeclSpec().getSourceRange().getBegin());
   }
 
-  if (InvalidDecl)
+  if (D.isInvalidType())
     NewFD->setInvalidDecl();
   
   // Set the lexical context. If the declarator has a C++
@@ -2079,7 +2085,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // function is also virtual if it overrides an already virtual
   // function. This is important to do here because it's part of the
   // declaration.
-  if (isVirtual && !InvalidDecl) {
+  if (isVirtual && !NewFD->isInvalidDecl()) {
     if (!isVirtualOkay) {
        Diag(D.getDeclSpec().getVirtualSpecLoc(), 
            diag::err_virtual_non_function);
@@ -2218,17 +2224,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 
   // Perform semantic checking on the function declaration.
   bool OverloadableAttrRequired = false; // FIXME: HACK!
-  if (CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
-                               /*FIXME:*/OverloadableAttrRequired))
-    InvalidDecl = true;
+  CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
+                           /*FIXME:*/OverloadableAttrRequired);
 
-  if (D.getCXXScopeSpec().isSet() && !InvalidDecl) {
+  if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
     // An out-of-line member function declaration must also be a
     // definition (C++ [dcl.meaning]p1).
     if (!IsFunctionDefinition) {
       Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
         << D.getCXXScopeSpec().getRange();
-      InvalidDecl = true;
+      NewFD->setInvalidDecl();
     } else if (!Redeclaration) {
       // The user tried to provide an out-of-line definition for a
       // function that is a member of a class or namespace, but there
@@ -2246,7 +2251,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
       // whether the parameter types are references).
       Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
         << cast<NamedDecl>(DC) << D.getCXXScopeSpec().getRange();
-      InvalidDecl = true;
+      NewFD->setInvalidDecl();
       
       LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName, 
                                               true);
@@ -2284,7 +2289,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // If this is a locally-scoped extern C function, update the
   // map of such names.
   if (CurContext->isFunctionOrMethod() && NewFD->isExternC(Context)
-      && !InvalidDecl)
+      && !NewFD->isInvalidDecl())
     RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
 
   return NewFD;
@@ -2300,18 +2305,21 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
 /// that have been instantiated via C++ template instantiation (called
 /// via InstantiateDecl).
 ///
-/// \returns true if there was an error, false otherwise.
-bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
                                     bool &Redeclaration,
                                     bool &OverloadableAttrRequired) {
-  bool InvalidDecl = false;
+  // If NewFD is already known erroneous, don't do any of this checking.
+  if (NewFD->isInvalidDecl())
+    return;
 
   // Semantic checking for this function declaration (in isolation).
   if (getLangOptions().CPlusPlus) {
     // C++-specific checks.
-    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
-      InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
-    else if (isa<CXXDestructorDecl>(NewFD)) {
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+      if (CheckConstructor(Constructor))
+        return NewFD->setInvalidDecl();
+    } else if (isa<CXXDestructorDecl>(NewFD)) {
       CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
       Record->setUserDeclaredDestructor(true);
       // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
@@ -2328,7 +2336,7 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
     // Extra checking for C++ overloaded operators (C++ [over.oper]).
     if (NewFD->isOverloadedOperator() &&
         CheckOverloadedOperatorDeclaration(NewFD))
-      InvalidDecl = true;
+      return NewFD->setInvalidDecl();
   }
 
   // C99 6.7.4p6:
@@ -2386,7 +2394,6 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
       if (!NewFD->getType()->getAsFunctionProtoType()) {
         Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype)
           << NewFD;
-        InvalidDecl = true;
         Redeclaration = true;
 
         // Turn this into a variadic function with no parameters.
@@ -2394,6 +2401,7 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
                        NewFD->getType()->getAsFunctionType()->getResultType(),
                        0, 0, true, 0);
         NewFD->setType(R);
+        return NewFD->setInvalidDecl();
       }
     }
 
@@ -2411,21 +2419,17 @@ bool Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
       // NewFD and OldDecl represent declarations that need to be
       // merged. 
       if (MergeFunctionDecl(NewFD, OldDecl))
-        InvalidDecl = true;
+        return NewFD->setInvalidDecl();
 
-      if (!InvalidDecl)
-        NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+      NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
     }
   }
 
-  if (getLangOptions().CPlusPlus && !CurContext->isRecord()) {
-    // In C++, check default arguments now that we have merged decls. Unless
-    // the lexical context is the class, because in this case this is done
-    // during delayed parsing anyway.
+  // In C++, check default arguments now that we have merged decls. Unless
+  // the lexical context is the class, because in this case this is done
+  // during delayed parsing anyway.
+  if (getLangOptions().CPlusPlus && !CurContext->isRecord())
     CheckCXXDefaultArguments(NewFD);
-  }
-
-  return InvalidDecl || NewFD->isInvalidDecl();
 }
 
 bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
@@ -2798,9 +2802,6 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
   if (getLangOptions().CPlusPlus)
     CheckExtraCXXDefaultArguments(D);
  
-  // In this context, we *do not* check D.getInvalidType(). If the declarator
-  // type was invalid, GetTypeForDeclarator() still returns a "valid" type,
-  // though it will not reflect the user specified type.
   QualType parmDeclType = GetTypeForDeclarator(D, S);
   if (parmDeclType.isNull()) {
     D.setInvalidType(true);
@@ -2850,7 +2851,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
                                       D.getIdentifierLoc(), II, T,
                                       parmDeclType, StorageClass, 0);
   
-  if (D.getInvalidType())
+  if (D.isInvalidType())
     New->setInvalidDecl();
 
   // Parameter declarators cannot be interface types. All ObjC objects are
@@ -3210,7 +3211,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
       TD->setTypedefForAnonDecl(NewTD);
   }
 
-  if (D.getInvalidType())
+  if (D.isInvalidType())
     NewTD->setInvalidDecl();
   return NewTD;
 }
@@ -3712,6 +3713,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
                                 Declarator *D) {
   IdentifierInfo *II = Name.getAsIdentifierInfo();
   bool InvalidDecl = false;
+  if (D) InvalidDecl = D->isInvalidType();
 
   // If we receive a broken type, recover by assuming 'int' and
   // marking this declaration as invalid.
@@ -3753,6 +3755,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   
   FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth,
                                        Mutable);
+  if (InvalidDecl)
+    NewFD->setInvalidDecl();
 
   if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
     Diag(Loc, diag::err_duplicate_member) << II;
@@ -3772,9 +3776,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
   if (T.isObjCGCWeak())
     Diag(Loc, diag::warn_attribute_weak_on_field);
 
-  if (InvalidDecl)
-    NewFD->setInvalidDecl();
-
   NewFD->setAccess(AS);
 
   // C++ [dcl.init.aggr]p1:
@@ -3820,16 +3821,15 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
   // example, unnamed unions inject all members into the struct namespace!
   
   QualType T = GetTypeForDeclarator(D, S);
-  bool InvalidDecl = D.getInvalidType();
-  if (T.isNull()) {
-    InvalidDecl = true;
-    T = Context.IntTy;
-  }
+ if (T.isNull()) {
+   D.setInvalidType();
+   T = Context.IntTy;
+ }
   
   if (BitWidth) {
     // 6.7.2.1p3, 6.7.2.1p4
     if (VerifyBitField(Loc, II, T, BitWidth)) {
-      InvalidDecl = true;
+      D.setInvalidType();
       DeleteExpr(BitWidth);
       BitWidth = 0;
     }
@@ -3844,7 +3844,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
   // than a variably modified type.
   if (T->isVariablyModifiedType()) {
     Diag(Loc, diag::err_typecheck_ivar_variable_size);
-    InvalidDecl = true;
+    D.setInvalidType();
   }
   
   // Get the visibility (access control) for this ivar.
@@ -3869,7 +3869,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
   // Process attributes attached to the ivar.
   ProcessDeclAttributes(NewID, D);
   
-  if (D.getInvalidType() || InvalidDecl)
+  if (D.isInvalidType())
     NewID->setInvalidDecl();
 
   if (II) {
index 82830ef4ad6f0b8f8d5e2e69f2a20772abcc7962..e3a0063b0d8b51235c95c794c175b30e8e9fd89e 100644 (file)
@@ -2547,7 +2547,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
   QualType ExDeclType = GetTypeForDeclarator(D, S);
   SourceLocation Begin = D.getDeclSpec().getSourceRange().getBegin();
 
-  bool Invalid = false;
+  bool Invalid = D.isInvalidType();
 
   // Arrays and functions decay.
   if (ExDeclType->isArrayType())
@@ -2597,15 +2597,15 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
 
   VarDecl *ExDecl = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
                                     II, ExDeclType, VarDecl::None, Begin);
-  if (D.getInvalidType() || Invalid)
-    ExDecl->setInvalidDecl();
-
-  if (D.getCXXScopeSpec().isSet()) {
+  if (D.getCXXScopeSpec().isSet() && !Invalid) {
     Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
       << D.getCXXScopeSpec().getRange();
-    ExDecl->setInvalidDecl();
+    Invalid = true;
   }
 
+  if (Invalid)
+    ExDecl->setInvalidDecl();
+  
   // Add the exception declaration into this scope.
   S->AddDecl(DeclPtrTy::make(ExDecl));
   if (II)
index 753fd5efc1bb7e7994bee86560ecfe0c3c9883c0..6b0c04440a8c4e4cf7d51a5752b1b45f0a84a461 100644 (file)
@@ -243,7 +243,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
   }
 
   QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip);
-  if (D.getInvalidType())
+  if (D.isInvalidType())
     return ExprError();
 
   if (CheckAllocatedType(AllocType, D))
index 4639511023c6450e9b37274caea933f10306f166..d7e81127a75347a710b36862d6fc757288ef5ab2 100644 (file)
@@ -124,9 +124,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
   // FIXME: In theory, we could have a previous declaration for
   // variables that are not static data members.
   bool Redeclaration = false;
-  if (SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration))
-    Var->setInvalidDecl();
-
+  SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration);
   Owner->addDecl(SemaRef.Context, Var);
 
   if (D->getInit()) {
@@ -322,9 +320,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
     PrevDecl = 0;
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
-  if (SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
-                                       /*FIXME:*/OverloadableAttrRequired))
-    Method->setInvalidDecl();
+  SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
 
   if (!Method->isInvalidDecl() || !PrevDecl)
     Owner->addDecl(SemaRef.Context, Method);
@@ -366,12 +363,10 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
     PrevDecl = 0;
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
-  if (SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
-                                       /*FIXME:*/OverloadableAttrRequired))
-    Constructor->setInvalidDecl();
+  SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
 
-  if (!Constructor->isInvalidDecl())
-    Owner->addDecl(SemaRef.Context, Constructor);
+  Owner->addDecl(SemaRef.Context, Constructor);
   return Constructor;
 }
 
@@ -396,9 +391,8 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
   NamedDecl *PrevDecl = 0;
-  if (SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
-                                       /*FIXME:*/OverloadableAttrRequired))
-    Destructor->setInvalidDecl();
+  SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
   Owner->addDecl(SemaRef.Context, Destructor);
   return Destructor;
 }
@@ -426,9 +420,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
   NamedDecl *PrevDecl = 0;
-  if (SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
-                                       /*FIXME:*/OverloadableAttrRequired))
-    Conversion->setInvalidDecl();
+  SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration,
+                                   /*FIXME:*/OverloadableAttrRequired);
   Owner->addDecl(SemaRef.Context, Conversion);
   return Conversion;  
 }
index 62d2489b345831231ebff09bd05280eaa93dc949..7519aff630a8ba93f517ff1ff3f3f6f97cfe03ec 100644 (file)
@@ -50,7 +50,8 @@ QualType Sema::adjustParameterType(QualType T) {
 /// \returns The type described by the declaration specifiers, or NULL
 /// if there was an error.
 QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
-                                     SourceLocation DeclLoc) {
+                                     SourceLocation DeclLoc,
+                                     bool &isInvalid) {
   // FIXME: Should move the logic from DeclSpec::Finish to here for validity
   // checking.
   QualType Result;
@@ -205,8 +206,15 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
           DeclLoc = DS.getSourceRange().getBegin();
         Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
           << DS.getSourceRange();
+        isInvalid = true;
       }
     }
+    
+    // If this is a reference to an invalid typedef, propagate the invalidity.
+    if (TypedefType *TDT = dyn_cast<TypedefType>(Result))
+      if (TDT->getDecl()->isInvalidDecl())
+        isInvalid = true;
+    
     // TypeQuals handled by caller.
     break;
   }
@@ -614,9 +622,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
       // the first return statement.
       T = Context.DependentTy;
     } else {
-      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc());
+      bool isInvalid = false;
+      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
       if (T.isNull())
         return T;
+      if (isInvalid)
+        D.setInvalidType(true);
     }
     break;
   }
index e9130c80a90e52941808f846178a5ef17c1db1e3..8c458008cb5c5cf01a5a27524934fa19eb0a0812 100644 (file)
@@ -6,11 +6,14 @@ void test() {
 
 
 // PR2400
-typedef xtype (*zend_stream_fsizer_t)(void* handle); // expected-error {{function cannot return array or function type}} expected-warning {{type specifier missing, defaults to 'int'}} expected-warning {{type specifier missing, defaults to 'int'}}
+typedef xtype (*x)(void* handle); // expected-error {{function cannot return array or function type}} expected-warning {{type specifier missing, defaults to 'int'}} expected-warning {{type specifier missing, defaults to 'int'}}
+
+typedef void ytype();
+
 
 typedef struct _zend_module_entry zend_module_entry;
 struct _zend_module_entry {
-    xtype globals_size; // expected-error {{field 'globals_size' declared as a function}}
+    ytype globals_size; // expected-error {{field 'globals_size' declared as a function}}
 };
 
 zend_module_entry openssl_module_entry = {
index 85b5ed76bd6bb2253101a73c15a06d9024b9e42f..e3c893c7771829e049d10732dacf1e5ce9164910 100644 (file)
@@ -23,8 +23,8 @@ int i1 = 1; // expected-note {{previous definition is here}}
 int i1 = 2; // expected-error {{redefinition of 'i1'}}
 int i1;
 int i1;
-extern int i1; // expected-note {{previous definition is here}}
-static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+extern int i5; // expected-note {{previous definition is here}}
+static int i5; // expected-error{{static declaration of 'i5' follows non-static declaration}}
 
 static int i2 = 5; // expected-note 1 {{previous definition is here}}
 int i2 = 3; // expected-error{{non-static declaration of 'i2' follows static declaration}}
@@ -47,8 +47,8 @@ int redef[];  // expected-note {{previous definition is here}}
 int redef[11]; // expected-error{{redefinition of 'redef'}}
 
 void func() {
-  extern int i1; // expected-note {{previous definition is here}}
-  static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+  extern int i6; // expected-note {{previous definition is here}}
+  static int i6; // expected-error{{static declaration of 'i6' follows non-static declaration}}
 }
 
 void func2(void)
index f2f9f43a10d4aeb4f9341f5233df4304b2afdef0..50fdc9622e4c7ecde2869e0278f4f7c5f2515218 100644 (file)
@@ -1,9 +1,10 @@
 // RUN: clang-cc -fsyntax-only -verify %s
 
-struct C {
-  virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}}
+struct C {  // expected-note {{candidate function}}
+  virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} \
+                      expected-note {{candidate function}}
 };
 
 void f() {
- C c;
+ C c;  // expected-error {{call to constructor of 'c' is ambiguous}}
 }
index 3ba5fd5946622b8e4e28f6b7578a3a881baefd00..c60045bb59d1e2d8647d9f3978cde6e9bab5e20b 100644 (file)
@@ -23,6 +23,7 @@ struct D {
     // expected-error{{destructor cannot be variadic}}
 };
 
+
 struct E;
 
 typedef E E_typedef;