[cfe-commits] r68251 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaInherit.cpp lib/Sema/SemaInherit.h lib/Sema/SemaLookup.cpp lib/Sema/SemaTemplate.cpp test/SemaCXX/member-name-lookup.cpp test/SemaCXX/using-directive.cpp test/SemaTemplate/nested-name-spec-template.cpp

Douglas Gregor dgregor at apple.com
Wed Apr 1 14:51:27 PDT 2009


Author: dgregor
Date: Wed Apr  1 16:51:26 2009
New Revision: 68251

URL: http://llvm.org/viewvc/llvm-project?rev=68251&view=rev
Log:
Make parsing a semantic analysis a little more robust following Sema
failures that involve malformed types, e.g., "typename X::foo" where
"foo" isn't a type, or "std::vector<void>" that doens't instantiate
properly.

Similarly, be a bit smarter in our handling of ambiguities that occur
in Sema::getTypeName, to eliminate duplicate error messages about
ambiguous name lookup.

This eliminates two XFAILs in test/SemaCXX, one of which was crying
out to us, trying to tell us that we were producing repeated error
messages.


Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaInherit.cpp
    cfe/trunk/lib/Sema/SemaInherit.h
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaCXX/member-name-lookup.cpp
    cfe/trunk/test/SemaCXX/using-directive.cpp
    cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Apr  1 16:51:26 2009
@@ -1005,8 +1005,8 @@
   
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
-  TypeTy *ParseClassName(SourceLocation &EndLocation, 
-                         const CXXScopeSpec *SS = 0);
+  TypeResult ParseClassName(SourceLocation &EndLocation, 
+                            const CXXScopeSpec *SS = 0);
   void ParseClassSpecifier(DeclSpec &DS, 
                            TemplateParameterLists *TemplateParams = 0,
                            AccessSpecifier AS = AS_none);
@@ -1065,7 +1065,7 @@
                                const CXXScopeSpec *SS,
                                SourceLocation TemplateKWLoc = SourceLocation(),
                                bool AllowTypeAnnotation = true);
-  bool AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
+  void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
   bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
                                  TemplateArgIsTypeList &TemplateArgIsType,
                                  TemplateArgLocationList &TemplateArgLocations);

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Apr  1 16:51:26 2009
@@ -558,8 +558,11 @@
     }
         
     case tok::annot_typename: {
-      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
-                                     Tok.getAnnotationValue());
+      if (Tok.getAnnotationValue())
+        isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                       Tok.getAnnotationValue());
+      else
+        DS.SetTypeSpecError();
       DS.SetRangeEnd(Tok.getAnnotationEndLoc());
       ConsumeToken(); // The typename
       
@@ -648,9 +651,7 @@
 
       // Turn the template-id annotation token into a type annotation
       // token, then try again to parse it as a type-specifier.
-      if (AnnotateTemplateIdTokenAsType())
-        DS.SetTypeSpecError();
-
+      AnnotateTemplateIdTokenAsType();
       continue;
     }
 
@@ -915,8 +916,11 @@
       
   // simple-type-specifier:
   case tok::annot_typename: {
-    isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
-                                   Tok.getAnnotationValue());
+    if (Tok.getAnnotationValue())
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+                                     Tok.getAnnotationValue());
+    else
+      DS.SetTypeSpecError();
     DS.SetRangeEnd(Tok.getAnnotationEndLoc());
     ConsumeToken(); // The typename
     
@@ -1893,11 +1897,11 @@
           // FIXME: Inaccurate.
           SourceLocation NameLoc = Tok.getLocation();
           SourceLocation EndLoc;
-          if (TypeTy *Type = ParseClassName(EndLoc)) {
-            D.setDestructor(Type, TildeLoc, NameLoc);
-          } else {
+          TypeResult Type = ParseClassName(EndLoc);
+          if (Type.isInvalid())
             D.SetIdentifier(0, TildeLoc);
-          }
+          else
+            D.setDestructor(Type.get(), TildeLoc, NameLoc);
         } else {
           Diag(Tok, diag::err_expected_class_name);
           D.SetIdentifier(0, TildeLoc);

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Apr  1 16:51:26 2009
@@ -301,21 +301,23 @@
 ///         identifier
 ///         simple-template-id
 /// 
-Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation,
-                                       const CXXScopeSpec *SS) {
+Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
+                                          const CXXScopeSpec *SS) {
   // Check whether we have a template-id that names a type.
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId 
       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     if (TemplateId->Kind == TNK_Type_template) {
-      if (AnnotateTemplateIdTokenAsType(SS))
-        return 0;
+      AnnotateTemplateIdTokenAsType(SS);
 
       assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
       TypeTy *Type = Tok.getAnnotationValue();
       EndLocation = Tok.getAnnotationEndLoc();
       ConsumeToken();
-      return Type;
+
+      if (Type)
+        return Type;
+      return true;
     }
 
     // Fall through to produce an error below.
@@ -323,7 +325,7 @@
 
   if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_class_name);
-    return 0;
+    return true;
   }
 
   // We have an identifier; check whether it is actually a type.
@@ -331,7 +333,7 @@
                                      Tok.getLocation(), CurScope, SS);
   if (!Type) {
     Diag(Tok, diag::err_expected_class_name);
-    return 0;
+    return true;
   }
 
   // Consume the identifier.
@@ -592,7 +594,7 @@
     if (IsVirtual) {
       // Complain about duplicate 'virtual'
       Diag(VirtualLoc, diag::err_dup_virtual)
-        << SourceRange(VirtualLoc, VirtualLoc);
+        << CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc));
     }
 
     IsVirtual = true;
@@ -607,8 +609,8 @@
 
   // Parse the class-name.
   SourceLocation EndLocation;
-  TypeTy *BaseType = ParseClassName(EndLocation, &SS);
-  if (!BaseType)
+  TypeResult BaseType = ParseClassName(EndLocation, &SS);
+  if (BaseType.isInvalid())
     return true;
   
   // Find the complete source range for the base-specifier.  
@@ -617,7 +619,7 @@
   // Notify semantic analysis that we have parsed a complete
   // base-specifier.
   return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
-                                    BaseType, BaseLoc);
+                                    BaseType.get(), BaseLoc);
 }
 
 /// getAccessSpecifierIfPresent - Determine whether the next token is

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Apr  1 16:51:26 2009
@@ -148,12 +148,11 @@
 
       if (TemplateId->Kind == TNK_Type_template || 
           TemplateId->Kind == TNK_Dependent_template_name) {
-        if (AnnotateTemplateIdTokenAsType(&SS))
-          SS.clear();
+        AnnotateTemplateIdTokenAsType(&SS);
+        SS.clear();
 
         assert(Tok.is(tok::annot_typename) && 
                "AnnotateTemplateIdTokenAsType isn't working");
-
         Token TypeToken = Tok;
         ConsumeToken();
         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
@@ -163,12 +162,15 @@
           SS.setBeginLoc(TypeToken.getLocation());
           HasScopeSpecifier = true;
         }
-
-        SS.setScopeRep(
-          Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 
-                                              TypeToken.getAnnotationValue(),
-                                              TypeToken.getAnnotationRange(),
-                                              CCLoc));
+        
+        if (TypeToken.getAnnotationValue())
+          SS.setScopeRep(
+            Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 
+                                                TypeToken.getAnnotationValue(),
+                                                TypeToken.getAnnotationRange(),
+                                                CCLoc));
+        else
+          SS.setScopeRep(0);
         SS.setEndLoc(CCLoc);
         continue;
       } else

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Apr  1 16:51:26 2009
@@ -588,8 +588,10 @@
 /// \brief Replaces a template-id annotation token with a type
 /// annotation token.
 ///
-/// \returns true if there was an error, false otherwise.
-bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
+/// If there was a failure when forming the type from the template-id,
+/// a type annotation token will still be created, but will have a
+/// NULL type pointer to signify an error.
+void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
   assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
 
   TemplateIdAnnotation *TemplateId 
@@ -610,16 +612,9 @@
                                   TemplateArgsPtr,
                                   TemplateId->getTemplateArgLocations(),
                                   TemplateId->RAngleLoc);
-  if (Type.isInvalid()) {
-    // FIXME: better recovery?
-    ConsumeToken();
-    TemplateId->Destroy();
-    return true;
-  }
-
   // Create the new "type" annotation token.
   Tok.setKind(tok::annot_typename);
-  Tok.setAnnotationValue(Type.get());
+  Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
   if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
     Tok.setLocation(SS->getBeginLoc());
 
@@ -629,8 +624,6 @@
   // class template specialization again.
   PP.ReplaceLastTokenWithAnnotation(Tok);
   TemplateId->Destroy();
-
-  return false;
 }
 
 /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).

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

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Apr  1 16:51:26 2009
@@ -851,22 +851,22 @@
         return false;
       }
 
-      if (AnnotateTemplateIdTokenAsType(0))
-        return false;
-
+      AnnotateTemplateIdTokenAsType(0);
       assert(Tok.is(tok::annot_typename) && 
              "AnnotateTemplateIdTokenAsType isn't working properly");
-      Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
-                                     Tok.getAnnotationValue());
+      if (Tok.getAnnotationValue())
+        Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
+                                       Tok.getAnnotationValue());
+      else
+        Ty = true;
     } else {
       Diag(Tok, diag::err_expected_type_name_after_typename)
         << SS.getRange();
       return false;
     }
 
-    // FIXME: better error recovery!
     Tok.setKind(tok::annot_typename);
-    Tok.setAnnotationValue(Ty.get());
+    Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get());
     Tok.setAnnotationEndLoc(Tok.getLocation());
     Tok.setLocation(TypenameLoc);
     PP.AnnotateCachedTokens(Tok);
@@ -925,7 +925,8 @@
       // template-id annotation in a context where we weren't allowed
       // to produce a type annotation token. Update the template-id
       // annotation token to a type annotation token now.
-      return !AnnotateTemplateIdTokenAsType(&SS);
+      AnnotateTemplateIdTokenAsType(&SS);
+      return true;
     }
   }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Apr  1 16:51:26 2009
@@ -755,7 +755,6 @@
       /// pointers used to reconstruct new'ed Decl*[] array containing
       /// found ambiguous decls. LookupResult is owner of this array.
       AmbiguousLookupStoresDecls
-
     } StoredKind;
 
     /// The first lookup result, whose contents depend on the kind of
@@ -939,6 +938,9 @@
 
     iterator begin();
     iterator end();
+
+    /// \brief Free the memory associated with this lookup.
+    void Destroy();
   };
 
 private:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr  1 16:51:26 2009
@@ -80,9 +80,34 @@
 
   case LookupResult::AmbiguousBaseSubobjectTypes:
   case LookupResult::AmbiguousBaseSubobjects:
-  case LookupResult::AmbiguousReference:
+  case LookupResult::AmbiguousReference: {
+    // Look to see if we have a type anywhere in the list of results.
+    for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
+         Res != ResEnd; ++Res) {
+      if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
+        IIDecl = *Res;
+        break;
+      }
+    }
+
+    if (!IIDecl) {
+      // None of the entities we found is a type, so there is no way
+      // to even assume that the result is a type. In this case, don't
+      // complain about the ambiguity. The parser will either try to
+      // perform this lookup again (e.g., as an object name), which
+      // will produce the ambiguity, or will complain that it expected
+      // a type name.
+      Result.Destroy();
+      return 0;
+    }
+
+    // We found a type within the ambiguous lookup; diagnose the
+    // ambiguity and then return that type. This might be the right
+    // answer, or it might not be, but it suppresses any attempt to
+    // perform the name lookup again.
     DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
-    return 0;
+    break;
+  }
 
   case LookupResult::Found:
     IIDecl = Result.getAsDecl();
@@ -3153,7 +3178,7 @@
       //
       // struct S s;
       //
-      // causes needless err_ovl_no_viable_function_in_init latter.
+      // causes needless "incomplete type" error later.
       Name = 0;
       PrevDecl = 0;
       Invalid = true;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInherit.cpp Wed Apr  1 16:51:26 2009
@@ -25,6 +25,34 @@
 
 using namespace clang;
 
+/// \brief Computes the set of declarations referenced by these base
+/// paths.
+void BasePaths::ComputeDeclsFound() {
+  assert(NumDeclsFound == 0 && !DeclsFound && 
+         "Already computed the set of declarations");
+  
+  std::set<NamedDecl *> Decls;
+  for (BasePaths::paths_iterator Path = begin(), PathEnd = end();
+       Path != PathEnd; ++Path)
+    Decls.insert(*Path->Decls.first);
+
+  NumDeclsFound = Decls.size();
+  DeclsFound = new NamedDecl * [NumDeclsFound];
+  std::copy(Decls.begin(), Decls.end(), DeclsFound);
+}
+
+NamedDecl **BasePaths::found_decls_begin() {
+  if (NumDeclsFound == 0)
+    ComputeDeclsFound();
+  return DeclsFound;
+}
+
+NamedDecl **BasePaths::found_decls_end() {
+  if (NumDeclsFound == 0)
+    ComputeDeclsFound();
+  return DeclsFound + NumDeclsFound;
+}
+
 /// isAmbiguous - Determines whether the set of paths provided is
 /// ambiguous, i.e., there are two or more paths that refer to
 /// different base class subobjects of the same type. BaseType must be

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.h (original)
+++ cfe/trunk/lib/Sema/SemaInherit.h Wed Apr  1 16:51:26 2009
@@ -132,8 +132,16 @@
     /// DetectedVirtual - The base class that is virtual.
     const RecordType *DetectedVirtual;
 
+    /// \brief Array of the declarations that have been found. This
+    /// array is constructed only if needed, e.g., to iterate over the
+    /// results within LookupResult.
+    NamedDecl **DeclsFound;
+    unsigned NumDeclsFound;
+
     friend class Sema;
 
+    void ComputeDeclsFound();
+
   public:
     typedef std::list<BasePath>::const_iterator paths_iterator;
     
@@ -143,15 +151,21 @@
                        bool RecordPaths = true,
                        bool DetectVirtual = true)
       : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
-        DetectVirtual(DetectVirtual), DetectedVirtual(0)
+        DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
+        NumDeclsFound(0)
     {}
 
+    ~BasePaths() { delete [] DeclsFound; }
+
     paths_iterator begin() const { return Paths.begin(); }
     paths_iterator end()   const { return Paths.end(); }
 
     BasePath&       front()       { return Paths.front(); }
     const BasePath& front() const { return Paths.front(); }
 
+    NamedDecl **found_decls_begin();
+    NamedDecl **found_decls_end();
+
     bool isAmbiguous(QualType BaseType);
 
     /// isFindingAmbiguities - Whether we are finding multiple paths

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Apr  1 16:51:26 2009
@@ -437,13 +437,16 @@
   case OverloadedDeclFromIdResolver:
     return *IdentifierResolver::iterator::getFromOpaqueValue(Current);
 
+  case AmbiguousLookupStoresBasePaths:
+    if (Result->Last)
+      return *reinterpret_cast<NamedDecl**>(Current);
+
+    // Fall through to handle the DeclContext::lookup_iterator we're
+    // storing.
+
   case OverloadedDeclFromDeclContext:
-    return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
-  
   case AmbiguousLookupStoresDecls:
-  case AmbiguousLookupStoresBasePaths:
-    assert(false && "Cannot look into ambiguous lookup results");
-    break;
+    return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
   }
 
   return 0;
@@ -470,39 +473,90 @@
     break;
   }
 
-  case OverloadedDeclFromDeclContext: {
+  case AmbiguousLookupStoresBasePaths: 
+    if (Result->Last) {
+      NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current);
+      ++I;
+      Current = reinterpret_cast<uintptr_t>(I);
+      break;
+    }
+    // Fall through to handle the DeclContext::lookup_iterator we're
+    // storing.
+
+  case OverloadedDeclFromDeclContext:
+  case AmbiguousLookupStoresDecls: {
     DeclContext::lookup_iterator I 
       = reinterpret_cast<DeclContext::lookup_iterator>(Current);
     ++I;
     Current = reinterpret_cast<uintptr_t>(I);
     break;
   }
-
-  case AmbiguousLookupStoresDecls:
-  case AmbiguousLookupStoresBasePaths:
-    assert(false && "Cannot look into ambiguous lookup results");
-    break;
   }
 
   return *this;
 }
 
 Sema::LookupResult::iterator Sema::LookupResult::begin() {
-  assert(!isAmbiguous() && "Lookup into an ambiguous result");
-  if (StoredKind != OverloadedDeclSingleDecl)
+  switch (StoredKind) {
+  case SingleDecl:
+  case OverloadedDeclFromIdResolver:
+  case OverloadedDeclFromDeclContext:
+  case AmbiguousLookupStoresDecls:
     return iterator(this, First);
-  OverloadedFunctionDecl * Ovl =
-    reinterpret_cast<OverloadedFunctionDecl*>(First);
-  return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_begin())));
+
+  case OverloadedDeclSingleDecl: {
+    OverloadedFunctionDecl * Ovl =
+      reinterpret_cast<OverloadedFunctionDecl*>(First);
+    return iterator(this, 
+                    reinterpret_cast<uintptr_t>(&(*Ovl->function_begin())));
+  }
+
+  case AmbiguousLookupStoresBasePaths:
+    if (Last)
+      return iterator(this, 
+              reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_begin()));
+    else
+      return iterator(this,
+              reinterpret_cast<uintptr_t>(getBasePaths()->front().Decls.first));
+  }
+
+  // Required to suppress GCC warning.
+  return iterator();
 }
 
 Sema::LookupResult::iterator Sema::LookupResult::end() {
-  assert(!isAmbiguous() && "Lookup into an ambiguous result");
-  if (StoredKind != OverloadedDeclSingleDecl)
+  switch (StoredKind) {
+  case SingleDecl:
+  case OverloadedDeclFromIdResolver:
+  case OverloadedDeclFromDeclContext:
+  case AmbiguousLookupStoresDecls:
     return iterator(this, Last);
-  OverloadedFunctionDecl * Ovl =
-    reinterpret_cast<OverloadedFunctionDecl*>(First);
-  return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_end())));
+
+  case OverloadedDeclSingleDecl: {
+    OverloadedFunctionDecl * Ovl =
+      reinterpret_cast<OverloadedFunctionDecl*>(First);
+    return iterator(this, 
+                    reinterpret_cast<uintptr_t>(&(*Ovl->function_end())));
+  }
+
+  case AmbiguousLookupStoresBasePaths:
+    if (Last)
+      return iterator(this, 
+               reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_end()));
+    else
+      return iterator(this, reinterpret_cast<uintptr_t>(
+                                     getBasePaths()->front().Decls.second));
+  }
+
+  // Required to suppress GCC warning.
+  return iterator();
+}
+
+void Sema::LookupResult::Destroy() {
+  if (BasePaths *Paths = getBasePaths())
+    delete Paths;
+  else if (getKind() == AmbiguousReference)
+    delete[] reinterpret_cast<NamedDecl **>(First);
 }
 
 static void
@@ -1071,8 +1125,7 @@
                                    SourceRange LookupRange) {
   assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
 
-  if (BasePaths *Paths = Result.getBasePaths())
-  {
+  if (BasePaths *Paths = Result.getBasePaths()) {
     if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) {
       QualType SubobjectType = Paths->front().back().Base->getType();
       Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
@@ -1080,11 +1133,13 @@
         << LookupRange;
 
       DeclContext::lookup_iterator Found = Paths->front().Decls.first;
-      while (isa<CXXMethodDecl>(*Found) && cast<CXXMethodDecl>(*Found)->isStatic())
+      while (isa<CXXMethodDecl>(*Found) && 
+             cast<CXXMethodDecl>(*Found)->isStatic())
         ++Found;
 
       Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
 
+      Result.Destroy();
       return true;
     } 
 
@@ -1102,20 +1157,18 @@
         Diag(D->getLocation(), diag::note_ambiguous_member_found);
     }
 
-    delete Paths;
+    Result.Destroy();
     return true;
   } else if (Result.getKind() == LookupResult::AmbiguousReference) {
-
     Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
 
     NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First),
-       **DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
+            **DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
 
     for (; DI != DEnd; ++DI)
       Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
 
-    delete[] reinterpret_cast<NamedDecl **>(Result.First);
-
+    Result.Destroy();
     return true;
   }
 
@@ -1466,7 +1519,6 @@
                                      AssociatedNamespaces, AssociatedClasses);
 
   // C++ [basic.lookup.argdep]p3:
-  //
   //   Let X be the lookup set produced by unqualified lookup (3.4.1)
   //   and let Y be the lookup set produced by argument dependent
   //   lookup (defined as follows). If X contains [...] then Y is

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr  1 16:51:26 2009
@@ -870,8 +870,11 @@
   QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
                                         &TemplateArgs[0], TemplateArgs.size(),
                                         RAngleLoc);
-  
   TemplateArgsIn.release();
+
+  if (Result.isNull())
+    return true;
+
   return Result.getAsOpaquePtr();
 }
 
@@ -2102,6 +2105,8 @@
     return true;
 
   QualType T = CheckTypenameType(NNS, II, SourceRange(TypenameLoc, IdLoc));
+  if (T.isNull())
+    return true;
   return T.getAsOpaquePtr();
 }
 

Modified: cfe/trunk/test/SemaCXX/member-name-lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-name-lookup.cpp?rev=68251&r1=68250&r2=68251&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-name-lookup.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-name-lookup.cpp Wed Apr  1 16:51:26 2009
@@ -1,36 +1,33 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
-// fails due to exact diagnostic matching
-
 struct A { 
-  int a;  // expected-note{{member found by ambiguous name lookup}}
+  int a;  // expected-note 4{{member found by ambiguous name lookup}}
   static int b;
-  static int c; // expected-note{{member found by ambiguous name lookup}}
+  static int c; // expected-note 4{{member found by ambiguous name lookup}}
 
   enum E { enumerator };
 
   typedef int type;
 
   static void f(int);
-  void f(float); // expected-note{{member found by ambiguous name lookup}}
+  void f(float); // expected-note 2{{member found by ambiguous name lookup}}
 
   static void static_f(int);
   static void static_f(double);
 };
 
 struct B : A {
-  int d; // expected-note{{member found by ambiguous name lookup}}
+  int d; // expected-note 2{{member found by ambiguous name lookup}}
 
   enum E2 { enumerator2 };
 
-  enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}}
 };
 
 struct C : A {
-  int c; // expected-note{{member found by ambiguous name lookup}}
-  int d; // expected-note{{member found by ambiguous name lookup}}
+  int c; // expected-note 2{{member found by ambiguous name lookup}}
+  int d; // expected-note 2{{member found by ambiguous name lookup}}
 
-  enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
 };
 
 struct D : B, C {
@@ -50,7 +47,7 @@
 
   D::E2 e2 = D::enumerator2; // okay
 
-  D::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}}
+  D::E3 e3; // expected-error{{multiple base classes}}
 }
 
 void D::test_lookup() {
@@ -70,18 +67,18 @@
 }
 
 struct B2 : virtual A {
-  int d; // expected-note{{member found by ambiguous name lookup}}
+  int d; // expected-note 2{{member found by ambiguous name lookup}}
 
   enum E2 { enumerator2 };
 
-  enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}}
 };
 
 struct C2 : virtual A {
-  int c; // expected-note{{member found by ambiguous name lookup}}
-  int d; // expected-note{{member found by ambiguous name lookup}}
+  int c; // expected-note 2{{member found by ambiguous name lookup}}
+  int d; // expected-note 2{{member found by ambiguous name lookup}}
 
-  enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
 };
 
 struct D2 : B2, C2 { 
@@ -147,6 +144,5 @@
 };
 
 struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 {
-  type t; // expected-error{{member 'type' found in multiple base classes of different types}} \
-          // expected-error{{expected ';' at end of declaration list}}
+  type t; // expected-error{{member 'type' found in multiple base classes of different types}}
 };

Modified: cfe/trunk/test/SemaCXX/using-directive.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-directive.cpp?rev=68251&r1=68250&r2=68251&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/using-directive.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-directive.cpp Wed Apr  1 16:51:26 2009
@@ -1,9 +1,7 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
-// fails due to exact diagnostic matching
 
 namespace A {
-  short i; // expected-note{{candidate found by name lookup is 'A::i'}}
+  short i; // expected-note 2{{candidate found by name lookup is 'A::i'}}
   namespace B {
     long i; // expected-note{{candidate found by name lookup is 'A::B::i'}}
     void f() {} // expected-note{{candidate function}}
@@ -58,7 +56,7 @@
 
 // FIXME: Do we want err_ovl_no_viable_function_in_init here?
 struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \
-                 expected-error{{no matching constructor}}
+                 expected-error{{incomplete type}}
 
 // FIXME: This case is incorrectly diagnosed!
 //K2 k3;
@@ -66,7 +64,7 @@
 
 class X { // expected-note{{candidate found by name lookup is 'X'}}
   // FIXME: produce a suitable error message for this
-  using namespace A; // expected-error{{expected unqualified-id}}
+  using namespace A; // expected-error{{expected member name or}}
 };
 
 namespace N {
@@ -96,7 +94,8 @@
 }
 
 namespace TwoTag {
-  struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}}
+  struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} \
+  // expected-note{{forward declaration}}
 }
 
 namespace FuncHidesTagAmbiguity {
@@ -105,6 +104,7 @@
   using namespace TwoTag;
 
   void test() {
-    (void)X(); // expected-error{{reference to 'X' is ambiguous}}
+    (void)X(); // expected-error{{reference to 'X' is ambiguous}} \
+      // FIXME: expected-error{{invalid use of incomplete type}}
   }
 }

Modified: cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp?rev=68251&r1=68250&r2=68251&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp Wed Apr  1 16:51:26 2009
@@ -52,7 +52,7 @@
 
 #if 0
 // FIXME: the following crashes the parser, because Sema has no way to
-// community that the "dependent" template-name N::template B doesn't
+// communicate that the "dependent" template-name N::template B doesn't
 // actually refer to a template.
 template<typename T>
 struct TestA {





More information about the cfe-commits mailing list