[cfe-commits] r49621 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclBase.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/Sema/IdentifierResolver.cpp lib/Sema/IdentifierResolver.h lib/Sema/SemaDecl.cpp lib/Sema/SemaType.cpp test/Sema/class-names.cpp

Douglas Gregor doug.gregor at gmail.com
Sun Apr 13 14:07:46 PDT 2008


Author: dgregor
Date: Sun Apr 13 16:07:44 2008
New Revision: 49621

URL: http://llvm.org/viewvc/llvm-project?rev=49621&view=rev
Log:
Introduce support for finding class and enum names via ordinary name lookup in C++

Added:
    cfe/trunk/test/Sema/class-names.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=49621&r1=49620&r2=49621&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sun Apr 13 16:07:44 2008
@@ -176,7 +176,11 @@
   /// list.  isVariadic indicates whether the argument list includes '...'.
   QualType getFunctionType(QualType ResultTy, QualType *ArgArray,
                            unsigned NumArgs, bool isVariadic);
-  
+
+  /// getTypeDeclType - Return the unique reference to the type for
+  /// the specified type declaration.
+  QualType getTypeDeclType(TypeDecl *Decl);
+
   /// getTypedefType - Return the unique reference to the type for the
   /// specified typename decl.
   QualType getTypedefType(TypedefDecl *Decl);

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=49621&r1=49620&r2=49621&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Sun Apr 13 16:07:44 2008
@@ -80,12 +80,14 @@
   };
 
   /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
-  /// labels, tags, members and ordinary identifiers.
+  /// labels, tags, members and ordinary identifiers. These are meant
+  /// as bitmasks, so that searches in C++ can look into the "tag" namespace
+  /// during ordinary lookup.
   enum IdentifierNamespace {
-    IDNS_Label,
-    IDNS_Tag,
-    IDNS_Member,
-    IDNS_Ordinary
+    IDNS_Label = 0x1,
+    IDNS_Tag = 0x2,
+    IDNS_Member = 0x4,
+    IDNS_Ordinary = 0x8
   };
   
   /// ObjCDeclQualifier - Qualifier used on types in method declarations

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=49621&r1=49620&r2=49621&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sun Apr 13 16:07:44 2008
@@ -994,10 +994,11 @@
 
 class TagType : public Type {
   TagDecl *decl;
+
+protected:
   TagType(TagDecl *D, QualType can) : Type(Tagged, can), decl(D) {}
-  friend class ASTContext;  // ASTContext creates these.
-public:
-    
+
+public:   
   TagDecl *getDecl() const { return decl; }
   
   virtual void getAsStringInternal(std::string &InnerString) const;
@@ -1014,7 +1015,8 @@
 /// RecordType - This is a helper class that allows the use of isa/cast/dyncast
 /// to detect TagType objects of structs/unions/classes.
 class RecordType : public TagType {
-  RecordType(); // DO NOT IMPLEMENT
+  explicit RecordType(RecordDecl *D) : TagType(cast<TagDecl>(D), QualType()) { }
+  friend class ASTContext;   // ASTContext creates these.
 public:
     
   RecordDecl *getDecl() const {
@@ -1040,7 +1042,8 @@
 /// EnumType - This is a helper class that allows the use of isa/cast/dyncast
 /// to detect TagType objects of enums.
 class EnumType : public TagType {
-  EnumType(); // DO NOT IMPLEMENT
+  explicit EnumType(EnumDecl *D) : TagType(cast<TagDecl>(D), QualType()) { }
+  friend class ASTContext;   // ASTContext creates these.
 public:
     
   EnumDecl *getDecl() const {

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=49621&r1=49620&r2=49621&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sun Apr 13 16:07:44 2008
@@ -788,6 +788,28 @@
   return QualType(FTP, 0);
 }
 
+/// getTypeDeclType - Return the unique reference to the type for the
+/// specified type declaration.
+QualType ASTContext::getTypeDeclType(TypeDecl *Decl) {
+  if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+  
+  if (TypedefDecl *Typedef = dyn_cast_or_null<TypedefDecl>(Decl))
+    return getTypedefType(Typedef);
+  else if (ObjCInterfaceDecl *ObjCInterface 
+             = dyn_cast_or_null<ObjCInterfaceDecl>(Decl))
+    return getObjCInterfaceType(ObjCInterface);
+  else if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Decl)) {
+    Decl->TypeForDecl = new RecordType(Record);
+    Types.push_back(Decl->TypeForDecl);
+    return QualType(Decl->TypeForDecl, 0);
+  } else if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Decl)) {
+    Decl->TypeForDecl = new EnumType(Enum);
+    Types.push_back(Decl->TypeForDecl);
+    return QualType(Decl->TypeForDecl, 0);    
+  } else
+    assert(false && "TypeDecl without a type?");
+}
+
 /// getTypedefType - Return the unique reference to the type for the
 /// specified typename decl.
 QualType ASTContext::getTypedefType(TypedefDecl *Decl) {
@@ -913,15 +935,7 @@
 /// specified TagDecl (struct/union/class/enum) decl.
 QualType ASTContext::getTagDeclType(TagDecl *Decl) {
   assert (Decl);
-
-  // The decl stores the type cache.
-  if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
-  
-  TagType* T = new TagType(Decl, QualType());
-  Types.push_back(T);  
-  Decl->TypeForDecl = T;
-
-  return QualType(T, 0);
+  return getTypeDeclType(Decl);
 }
 
 /// getSizeType - Return the unique type for "size_t" (C99 7.17), the result 

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

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Sun Apr 13 16:07:44 2008
@@ -15,6 +15,7 @@
 #include "IdentifierResolver.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/AST/Decl.h"
+#include "clang/Parse/Scope.h"
 #include <list>
 #include <vector>
 
@@ -113,6 +114,25 @@
   } else
     IDI = toIdDeclInfo(Ptr);
 
+  // C++ [basic.scope]p4:
+  //   -- exactly one declaration shall declare a class name or
+  //   enumeration name that is not a typedef name and the other
+  //   declarations shall all refer to the same object or
+  //   enumerator, or all refer to functions and function templates;
+  //   in this case the class name or enumeration name is hidden.
+  if (isa<TagDecl>(D)) {
+    // We are pushing the name of a tag (enum or class).
+    IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
+    if (S->isDeclScope(*TopIter)) {
+      // There is already a declaration with the same name in the same
+      // scope. It must be found before we find the new declaration,
+      // so swap the order on the shadowed declaration stack.
+      NamedDecl *Temp = *TopIter;
+      *TopIter = D;
+      D = Temp;
+    }
+  }
+
   IDI->PushShadowed(D);
 }
 
@@ -159,16 +179,15 @@
 
 /// Lookup - Find the non-shadowed decl that belongs to a particular
 /// Decl::IdentifierNamespace.
-NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NSI) {
+NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
   assert(II && "null param passed");
-  Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
   void *Ptr = II->getFETokenInfo<void>();
 
   if (!Ptr) return NULL;
 
   if (isDeclPtr(Ptr)) {
     NamedDecl *D = static_cast<NamedDecl*>(Ptr);
-    return (D->getIdentifierNamespace() == NS) ? D : NULL;
+    return (D->getIdentifierNamespace() & NS) ? D : NULL;
   }
 
   IdDeclInfo *IDI = toIdDeclInfo(Ptr);
@@ -178,7 +197,7 @@
   for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
        SI != IDI->shadowed_begin(); --SI) {
     NamedDecl *D = *(SI-1);
-    if (D->getIdentifierNamespace() == NS)
+    if (D->getIdentifierNamespace() & NS)
       return D;
   }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.h Sun Apr 13 16:07:44 2008
@@ -38,8 +38,8 @@
   /// The decl must already be part of the decl chain.
   void RemoveDecl(NamedDecl *D);
 
-  /// Lookup - Find the non-shadowed decl that belongs to a particular
-  /// Decl::IdentifierNamespace.
+  /// Lookup - Find the non-shadowed decl that belongs to one or more
+  /// of the specified Decl::IdentifierNamespaces.
   NamedDecl *Lookup(const IdentifierInfo *II, unsigned NSI);
 
 private:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 13 16:07:44 2008
@@ -35,7 +35,9 @@
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) {
   Decl *IIDecl = LookupDecl(&II, Decl::IDNS_Ordinary, S, false);
 
-  if (IIDecl && (isa<TypedefDecl>(IIDecl) || isa<ObjCInterfaceDecl>(IIDecl)))
+  if (IIDecl && (isa<TypedefDecl>(IIDecl) || 
+                 isa<ObjCInterfaceDecl>(IIDecl) ||
+                 isa<TagDecl>(IIDecl)))
     return IIDecl;
   return 0;
 }
@@ -102,7 +104,9 @@
 Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI,
                        Scope *S, bool enableLazyBuiltinCreation) {
   if (II == 0) return 0;
-  Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
+  unsigned NS = NSI;
+  if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
+    NS |= Decl::IDNS_Tag;
 
   // Scan up the scope chain looking for a decl that matches this identifier
   // that is in the appropriate namespace.  This search should not take long, as
@@ -113,7 +117,7 @@
   // If we didn't find a use of this identifier, and if the identifier
   // corresponds to a compiler builtin, create the decl object for the builtin
   // now, injecting it into translation unit scope, and return it.
-  if (NS == Decl::IDNS_Ordinary) {
+  if (NS & Decl::IDNS_Ordinary) {
     if (enableLazyBuiltinCreation) {
       // If this is a builtin on this (or all) targets, create the decl.
       if (unsigned BuiltinID = II->getBuiltinID())
@@ -746,7 +750,13 @@
   Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S);
   ScopedDecl *New;
   bool InvalidDecl = false;
-  
+ 
+  // In C++, the previous declaration we find might be a tag type
+  // (class or enum). In this case, the new declaration will hide the
+  // tag type. 
+  if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
+    PrevDecl = 0;
+
   QualType R = GetTypeForDeclarator(D, S);
   assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sun Apr 13 16:07:44 2008
@@ -105,7 +105,7 @@
            DS.getTypeSpecSign() == 0 &&
            "Can't handle qualifiers on typedef names yet!");
     // TypeQuals handled by caller.
-    Result = Context.getTagDeclType(cast<TagDecl>(D));
+    Result = Context.getTypeDeclType(cast<TypeDecl>(D));
     break;
   }    
   case DeclSpec::TST_typedef: {
@@ -114,6 +114,7 @@
     assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
            DS.getTypeSpecSign() == 0 &&
            "Can't handle qualifiers on typedef names yet!");
+
     // FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so
     // we have this "hack" for now... 
     if (ObjCInterfaceDecl *ObjCIntDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
@@ -140,7 +141,7 @@
       }
     }
     // TypeQuals handled by caller.
-    Result = Context.getTypedefType(cast<TypedefDecl>(D));
+    Result = Context.getTypeDeclType(dyn_cast<TypeDecl>(D));
     break;
   }
   case DeclSpec::TST_typeofType:

Added: cfe/trunk/test/Sema/class-names.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/class-names.cpp?rev=49621&view=auto

==============================================================================
--- cfe/trunk/test/Sema/class-names.cpp (added)
+++ cfe/trunk/test/Sema/class-names.cpp Sun Apr 13 16:07:44 2008
@@ -0,0 +1,50 @@
+// RUN: clang -fsyntax-only -verify %s
+class C { };
+
+C c;
+
+void D(int);
+
+class D {}; // expected-error{{previous use is here}}
+
+void foo()
+{
+  D(5);
+  class D d;
+}
+
+class D; 
+
+enum D; // expected-error{{use of 'D' with tag type that does not match previous declaration}}
+
+class A * A;
+
+class A * a2;
+
+void bar()
+{
+  A = 0;
+}
+
+void C(int);
+
+void bar2()
+{
+  C(17);
+}
+
+extern int B;
+class B;
+class B {};
+int B;
+
+enum E { e1_val };
+E e1;
+
+void E(int);
+
+void bar3() {
+  E(17);
+}
+
+enum E e2;

Propchange: cfe/trunk/test/Sema/class-names.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Sema/class-names.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Sema/class-names.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list