[cfe-commits] r70020 - in /cfe/trunk: 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

Chris Lattner sabre at nondot.org
Sat Apr 25 01:06:11 PDT 2009


Author: lattner
Date: Sat Apr 25 03:06:05 2009
New Revision: 70020

URL: http://llvm.org/viewvc/llvm-project?rev=70020&view=rev
Log:
This is a pretty big cleanup for how invalid decl/type are handle.
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.



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

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Sat Apr 25 03:06:05 2009
@@ -1017,8 +1017,8 @@
 
   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; 
   }
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Apr 25 03:06:05 2009
@@ -37,7 +37,7 @@
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   ParseDeclarator(DeclaratorInfo);
   
-  if (DeclaratorInfo.getInvalidType())
+  if (DeclaratorInfo.isInvalidType())
     return true;
 
   return Actions.ActOnTypeName(CurScope, DeclaratorInfo);

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Apr 25 03:06:05 2009
@@ -1338,7 +1338,7 @@
     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.

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Apr 25 03:06:05 2009
@@ -860,7 +860,7 @@
     }
     ParenTypeId = false;
   }
-  if (DeclaratorInfo.getInvalidType()) {
+  if (DeclaratorInfo.isInvalidType()) {
     SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
     return ExprError();
   }
@@ -938,7 +938,7 @@
     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.

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Apr 25 03:06:05 2009
@@ -326,7 +326,8 @@
   // 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 @@
                                         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 @@
 
   /// 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.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 25 03:06:05 2009
@@ -471,11 +471,16 @@
 /// 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 @@
       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 @@
   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 @@
       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 @@
   //   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 @@
   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 @@
 /// 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 @@
     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 @@
       (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 @@
            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 @@
         !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 @@
 
   // Keep a chain of previous declarations.
   New->setPreviousDeclaration(Old);
-
-  return false;
 }
 
 /// CheckParmsForFunctionDef - Check that the parameters of the given
@@ -1337,7 +1343,7 @@
   // 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 @@
   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 @@
   if (D.getCXXScopeSpec().isInvalid()) {
     DC = CurContext;
     PrevDecl = 0;
-    InvalidDecl = true;
+    D.setInvalidType();
   } else if (!D.getCXXScopeSpec().isSet()) {
     LookupNameKind NameKind = LookupOrdinaryName;
 
@@ -1430,14 +1435,16 @@
       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 @@
 
   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 @@
   
   // 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 @@
 
 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 @@
 
   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 @@
   // 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 @@
           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 @@
 
 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 @@
     // 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 @@
     // 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 @@
                           // 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 @@
       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 @@
 /// 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 @@
   // 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 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 @@
       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 @@
   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 @@
                              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 @@
     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 @@
   } 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 @@
                                    /*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 @@
            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 @@
                                  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 @@
   // 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 @@
 
   // 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 @@
       // 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 @@
   // 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 @@
 /// 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 @@
     // 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 @@
       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 @@
                        NewFD->getType()->getAsFunctionType()->getResultType(),
                        0, 0, true, 0);
         NewFD->setType(R);
+        return NewFD->setInvalidDecl();
       }
     }
 
@@ -2411,21 +2419,17 @@
       // 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 @@
   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 @@
                                       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 @@
       TD->setTypedefForAnonDecl(NewTD);
   }
 
-  if (D.getInvalidType())
+  if (D.isInvalidType())
     NewTD->setInvalidDecl();
   return NewTD;
 }
@@ -3712,6 +3713,7 @@
                                 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 *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 @@
   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 @@
   // 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 @@
   // 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 @@
   // Process attributes attached to the ivar.
   ProcessDeclAttributes(NewID, D);
   
-  if (D.getInvalidType() || InvalidDecl)
+  if (D.isInvalidType())
     NewID->setInvalidDecl();
 
   if (II) {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Apr 25 03:06:05 2009
@@ -2547,7 +2547,7 @@
   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 @@
 
   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)

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Apr 25 03:06:05 2009
@@ -243,7 +243,7 @@
   }
 
   QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip);
-  if (D.getInvalidType())
+  if (D.isInvalidType())
     return ExprError();
 
   if (CheckAllocatedType(AllocType, D))

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Apr 25 03:06:05 2009
@@ -124,9 +124,7 @@
   // 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 @@
     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 @@
     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 @@
   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 @@
   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;  
 }

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Apr 25 03:06:05 2009
@@ -50,7 +50,8 @@
 /// \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 @@
           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 @@
       // 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;
   }

Modified: cfe/trunk/test/Sema/invalid-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/invalid-decl.c?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/test/Sema/invalid-decl.c (original)
+++ cfe/trunk/test/Sema/invalid-decl.c Sat Apr 25 03:06:05 2009
@@ -6,11 +6,14 @@
 
 
 // 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 = {

Modified: cfe/trunk/test/Sema/tentative-decls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tentative-decls.c?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/test/Sema/tentative-decls.c (original)
+++ cfe/trunk/test/Sema/tentative-decls.c Sat Apr 25 03:06:05 2009
@@ -23,8 +23,8 @@
 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[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)

Modified: cfe/trunk/test/SemaCXX/constructor-recovery.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-recovery.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-recovery.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-recovery.cpp Sat Apr 25 03:06:05 2009
@@ -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}}
 }

Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=70020&r1=70019&r2=70020&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Sat Apr 25 03:06:05 2009
@@ -23,6 +23,7 @@
     // expected-error{{destructor cannot be variadic}}
 };
 
+
 struct E;
 
 typedef E E_typedef;





More information about the cfe-commits mailing list