]> granicus.if.org Git - clang/commitdiff
Test "merging" of typedef types across distinct modules. At present,
authorDouglas Gregor <dgregor@apple.com>
Tue, 3 Jan 2012 23:26:26 +0000 (23:26 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 3 Jan 2012 23:26:26 +0000 (23:26 +0000)
the AST reader doesn't actually perform a merge, because name lookup
knows how to merge identical typedefs together.

As part of this, teach C/Objective-C name lookup to return multiple
results in all cases, rather than first digging through the attributes
to see if the value is overloadable. This way, we'll catch ambiguous
lookups in C/Objective-C.

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

lib/AST/Decl.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaLookup.cpp
test/Modules/Inputs/redecl-merge-left.h
test/Modules/Inputs/redecl-merge-right.h
test/Modules/redecl-merge.m

index 31a9b3b2929f50f4fd72d7cd08862b911fc02c0f..479f80f1dd4d4cddb7cb0b33243d0eb65faa2d34 100644 (file)
@@ -938,6 +938,12 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
                                         cast<UsingDecl>(OldD)->getQualifier());
   }
 
+  // A typedef of an Objective-C class type can replace an Objective-C class
+  // declaration or definition, and vice versa.
+  if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
+      (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD)))
+    return true;
+  
   // For non-function declarations, if the declarations are of the
   // same kind then this must be a redeclaration, or semantic analysis
   // would not have given us the new declaration.
index 9583ab6327f0a6ef998b7dbfb96785626c54c9ff..43c9af58bc983322f09e0a382a72c32b8b7aae52 100644 (file)
@@ -8010,8 +8010,6 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
     // lookup.  This is only actually possible in C++, where a few
     // things like templates still live in the tag namespace.
     } else {
-      assert(getLangOptions().CPlusPlus);
-
       // Use a better diagnostic if an elaborated-type-specifier
       // found the wrong kind of type on the first
       // (non-redeclaration) lookup.
index 4f53487dcdbb215b2d71c4cb4bbb76b20ec6bf07..f836a077b6bb045dff2d5ec1c8576b7d712bbfc6 100644 (file)
@@ -1177,30 +1177,31 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
                 
         R.addDecl(D);
 
-        if ((*I)->getAttr<OverloadableAttr>()) {
-          // If this declaration has the "overloadable" attribute, we
-          // might have a set of overloaded functions.
-
-          // Figure out what scope the identifier is in.
-          while (!(S->getFlags() & Scope::DeclScope) ||
-                 !S->isDeclScope(*I))
-            S = S->getParent();
-
-          // Find the last declaration in this scope (with the same
-          // name, naturally).
-          IdentifierResolver::iterator LastI = I;
-          for (++LastI; LastI != IEnd; ++LastI) {
-            if (!S->isDeclScope(*LastI))
-              break;
-            
-            D = getVisibleDecl(*LastI);
-            if (D)
-              R.addDecl(D);
-          }
+        // Check whether there are any other declarations with the same name
+        // and in the same scope.
+
+        // Figure out what scope the identifier is in.
+        while (S->getParent() &&
+               (!(S->getFlags() & Scope::DeclScope) ||
+                !S->isDeclScope(*I)))
+          S = S->getParent();
+
+        // Find the last declaration in this scope (with the same
+        // name, naturally).
+        IdentifierResolver::iterator LastI = I;
+        for (++LastI; LastI != IEnd; ++LastI) {
+          if (!S->isDeclScope(*LastI))
+            break;
+          
+          if (!(*LastI)->isInIdentifierNamespace(IDNS))
+            continue;
+          
+          D = getVisibleDecl(*LastI);
+          if (D)
+            R.addDecl(D);
         }
 
         R.resolveKind();
-
         return true;
       }
   } else {
index b21271b14621ace38c5479496442490925a24fd8..47f3492f309b319997b3455d123a82d9d488c337 100644 (file)
@@ -56,6 +56,9 @@ struct S4 {
 struct S3 *produce_S3(void);
 void consume_S4(struct S4*);
 
+typedef int T1;
+typedef float T2;
+
 #ifdef __cplusplus
 template<typename T> class Vector;
 
index 686a96228a19f655a7573ff73e1e792d3f421efb..315a9c37fff5e45ec632e0c09d3276e105633d03 100644 (file)
@@ -59,6 +59,9 @@ struct S4;
 void consume_S3(struct S3*);
 struct S4 *produce_S4(void);
 
+typedef int T1;
+typedef double T2;
+
 #ifdef __cplusplus
 template<typename T> class Vector { 
 public:
index c0e83e8a86495bfbd14a962b897e636ca5d4a4ca..44d427c4c7551d6ee115b257267cdacf9ef3bba9 100644 (file)
@@ -55,6 +55,15 @@ void testTagMerge() {
   s3.s3_field = 0;
 }
 
+void testTypedefMerge(int i, double d) {
+  T1 *ip = &i;
+  // in other file: expected-note{{candidate found by name lookup is 'T2'}}
+  // FIXME: Typedefs aren't actually merged in the sense of other merges, because
+  // we should only merge them when the types are identical.
+  // in other file: expected-note{{candidate found by name lookup is 'T2'}}
+  T2 *dp = &d; // expected-error{{reference to 'T2' is ambiguous}}
+}
+
 // Test redeclarations of entities in explicit submodules, to make
 // sure we're maintaining the declaration chains even when normal name
 // lookup can't see what we're looking for.