/// 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);
};
/// 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
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;
/// 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 {
/// 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 {
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) {
/// 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
#include "IdentifierResolver.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Decl.h"
+#include "clang/Parse/Scope.h"
#include <list>
#include <vector>
} 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);
}
/// 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);
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;
}
/// 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:
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;
}
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
// 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())
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");
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: {
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)) {
}
}
// TypeQuals handled by caller.
- Result = Context.getTypedefType(cast<TypedefDecl>(D));
+ Result = Context.getTypeDeclType(dyn_cast<TypeDecl>(D));
break;
}
case DeclSpec::TST_typeofType:
--- /dev/null
+// 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;