]> granicus.if.org Git - clang/commitdiff
Diagnose ambiguities in getTypeName. Fixes http://llvm.org/bugs/show_bug.cgi?id=3475
authorDouglas Gregor <dgregor@apple.com>
Wed, 4 Feb 2009 17:00:24 +0000 (17:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 4 Feb 2009 17:00:24 +0000 (17:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63737 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/Parse/MinimalAction.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/member-name-lookup.cpp

index ffbb346380b879731f822e5bcc2457a422d81b39..7d5bf4579ebb4ed911c4d14e7e6ce88571acd46a 100644 (file)
@@ -135,8 +135,8 @@ public:
   /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
   /// namespace) that the identifier must be a member of.
   /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
-  virtual TypeTy *getTypeName(IdentifierInfo &II, Scope *S,
-                             const CXXScopeSpec *SS = 0) = 0;
+  virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                              Scope *S, const CXXScopeSpec *SS = 0) = 0;
 
   /// isCurrentClassName - Return true if the specified name is the
   /// name of the innermost C++ class type currently being defined.
@@ -1331,8 +1331,8 @@ public:
 
   /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to
   /// determine whether the name is a typedef or not in this scope.
-  virtual TypeTy *getTypeName(IdentifierInfo &II, Scope *S,
-                              const CXXScopeSpec *SS);
+  virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                              Scope *S, const CXXScopeSpec *SS);
 
   /// isCurrentClassName - Always returns false, because MinimalAction
   /// does not support C++ classes with constructors.
index e19100dc10456e228f7d68d4503fce5cc676621c..c34ac3478c45b1f3f543794d64ee068ea061d3ee 100644 (file)
@@ -695,7 +695,7 @@ private:
       return false;
     
     IdentifierInfo *II = Tok.getIdentifierInfo();
-    if (Actions.getTypeName(*II, CurScope))
+    if (Actions.getTypeName(*II, Tok.getLocation(), CurScope))
       return true;
     
     return II == Ident_super;
index 6fd5fc03152ba870ff52fc78b2fbb1bd291fd47e..2d6c9a6ba5642b2b0ac0824989021bfcd293ec33 100644 (file)
@@ -80,8 +80,8 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
 ///
 /// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
 Action::TypeTy *
-MinimalAction::getTypeName(IdentifierInfo &II, Scope *S,
-                           const CXXScopeSpec *SS) {
+MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
+                           Scope *S, const CXXScopeSpec *SS) {
   if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
     if (TI->isTypeName)
       return TI;
index cc1e9970e9d1348d91adad63c8f530339be42097..114f4cb5703ac8d4f1fd538a88579ebbd664c3ba 100644 (file)
@@ -484,8 +484,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
           GetLookAheadToken(2).is(tok::l_paren))
         goto DoneWithDeclSpec;
 
-      TypeTy *TypeRep = Actions.getTypeName(*NextToken().getIdentifierInfo(),
-                                            CurScope, &SS);
+      Token Next = NextToken();
+      TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
+                                            Next.getLocation(), CurScope, &SS);
       if (TypeRep == 0)
         goto DoneWithDeclSpec;
 
@@ -538,7 +539,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
         goto DoneWithDeclSpec;
       
       // It has to be available as a typedef too!
-      TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), CurScope);
+      TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), 
+                                            Tok.getLocation(), CurScope);
       if (TypeRep == 0)
         goto DoneWithDeclSpec;
       
@@ -1737,7 +1739,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
         // constructor name. 
         else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
           D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
-                                               CurScope),
+                                               Tok.getLocation(), CurScope),
                            Tok.getLocation());
         // This is a normal identifier.
         else
@@ -2191,7 +2193,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
     IdentifierInfo *ParmII = Tok.getIdentifierInfo();
 
     // Reject 'typedef int y; int test(x, y)', but continue parsing.
-    if (Actions.getTypeName(*ParmII, CurScope))
+    if (Actions.getTypeName(*ParmII, Tok.getLocation(), CurScope))
       Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
     
     // Verify that the argument identifier has not already been mentioned.
index 628331fd1d4d256150797a65f95178185714756f..1fbe32a4591c9befcf9f25b06e033b8b86fe9cc7 100644 (file)
@@ -232,7 +232,8 @@ Parser::TypeTy *Parser::ParseClassName(const CXXScopeSpec *SS) {
   }
 
   // We have an identifier; check whether it is actually a type.
-  TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(), CurScope, SS);
+  TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(), 
+                                     Tok.getLocation(), CurScope, SS);
   if (!Type) {
     Diag(Tok, diag::err_expected_class_name);
     return 0;
index 8685a599d2fd3d417f674b46ecc0dbb90d79aaee..c5c7dd4733f2ec1ae974fb260c921abb7e0e1248 100644 (file)
@@ -758,7 +758,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
   if (Tok.is(tok::identifier)) {
     // Determine whether the identifier is a type name.
     if (TypeTy *Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), 
-                                         CurScope, &SS)) {
+                                         Tok.getLocation(), CurScope, &SS)) {
       // This is a typename. Replace the current token in-place with an
       // annotation type token.
       Tok.setKind(tok::annot_typename);
index 724a57ed42b3985491b6ebf395146180de9ae95a..9810ba0cb57e6b513a76bca4d0156a42ed740880 100644 (file)
@@ -281,8 +281,8 @@ public:
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
   //
-  virtual TypeTy *getTypeName(IdentifierInfo &II, Scope *S,
-                              const CXXScopeSpec *SS);
+  virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, 
+                              Scope *S, const CXXScopeSpec *SS);
   virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup) {
     return ActOnDeclarator(S, D, LastInGroup, false);
   }
index 66b72ecad4f03d5daee151beb24a173a7154659f..fbf4be79eb5e19d7824e1c1953cbb735af14fcf5 100644 (file)
 
 using namespace clang;
 
-Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S,
-                                const CXXScopeSpec *SS) {
+Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                                Scope *S, const CXXScopeSpec *SS) {
   Decl *IIDecl = 0;
   LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false);
   switch (Result.getKind()) {
     case LookupResult::NotFound:
     case LookupResult::FoundOverloaded:
+      return 0;
+
     case LookupResult::AmbiguousBaseSubobjectTypes:
     case LookupResult::AmbiguousBaseSubobjects:
-      // FIXME: In the event of an ambiguous lookup, we could visit all of
-      // the entities found to determine whether they are all types. This
-      // might provide better diagnostics.
     case LookupResult::AmbiguousReference:
-    // FIXME: We need source location of identifier to diagnose more correctly.
+      DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
       return 0;
+
     case LookupResult::Found:
       IIDecl = Result.getAsDecl();
       break;
index 201d8b3ca86c16e5eedb5e2910583eff245b5512..2175ad3b9367939668d61b2016626756c4480621 100644 (file)
@@ -691,7 +691,7 @@ Sema::ActOnMemInitializer(DeclTy *ConstructorD,
   }
 
   // It didn't name a member, so see if it names a class.
-  TypeTy *BaseTy = getTypeName(*MemberOrBase, S, 0/*SS*/);
+  TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, 0/*SS*/);
   if (!BaseTy)
     return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
       << MemberOrBase << SourceRange(IdLoc, RParenLoc);
index f48a99add4d75f889ac697b812861de102d15cec..9e4b51fd748512953ab253ab2bf2ef19ba73fdb4 100644 (file)
@@ -133,13 +133,18 @@ void G::test_virtual_lookup() {
 
 
 struct HasMemberType1 {
-  struct type { };
+  struct type { }; // expected-note{{member found by ambiguous name lookup}}
 };
 
 struct HasMemberType2 {
-  struct type { };
+  struct type { }; // expected-note{{member found by ambiguous name lookup}}
 };
 
 struct HasAnotherMemberType : HasMemberType1, HasMemberType2 { 
   struct type { };
 };
+
+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}}
+};