Create a new TypeNameType class, which represents typedefs as types. This

allows us to handle stuff like:

typedef int G;
 ..
  X = sizeof(G);

llvm-svn: 39189
This commit is contained in:
Chris Lattner 2006-11-20 04:02:15 +00:00
parent 2ebe4bb64d
commit d0342e5989
7 changed files with 66 additions and 19 deletions

View File

@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include "clang/Lex/Preprocessor.h"
using namespace llvm;
using namespace clang;
@ -119,3 +119,20 @@ TypeRef ASTContext::getArrayType(TypeRef EltTy,ArrayType::ArraySizeModifier ASM,
}
/// getTypeDeclType - Return the unique reference to the type for the
/// specified typename decl.
TypeRef ASTContext::getTypeDeclType(TypeDecl *Decl) {
// FIXME: This is obviously braindead!
// Unique TypeDecl, to guarantee there is only one TypeDeclType.
for (unsigned i = 0, e = Types.size(); i != e; ++i)
if (TypeNameType *Ty = dyn_cast<TypeNameType>(Types[i]))
if (Ty->getDecl() == Decl)
return Types[i];
// FIXME: does this lose qualifiers from the typedef??
Type *Canonical = Decl->getType().getTypePtr();
Types.push_back(new TypeNameType(Decl, Canonical));
return Types.back();
}

View File

@ -73,10 +73,18 @@ static TypeRef ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
assert(0 && "FIXME: GNU decimal extensions not supported yet!");
//DeclSpec::TST_enum:
//DeclSpec::TST_union:
//DeclSpec::TST_struct:
//DeclSpec::TST_typedef:
//case DeclSpec::TST_enum:
//case DeclSpec::TST_union:
//case DeclSpec::TST_struct:
case DeclSpec::TST_typedef: {
Decl *D = (Decl *)DS.TypenameRep;
assert(D && "Didn't get a decl for a typedef?");
// FIXME: apply type quals!
assert(DS.TypeSpecWidth == 0 && DS.TypeSpecComplex == 0 &&
DS.TypeSpecSign == 0 && DS.TypeQualifiers == 0 &&
"Can't handle qualifiers on typedef names yet!");
return Ctx.getTypeDeclType(cast<TypedefDecl>(D));
}
}
}

View File

@ -11,7 +11,9 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/IdentifierTable.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include <iostream>
using namespace llvm;
using namespace clang;
@ -94,3 +96,7 @@ void ArrayType::getAsString(std::string &S) const {
ElementType.getAsString(S);
}
void TypeNameType::getAsString(std::string &InnerString) const {
InnerString += getDecl()->getIdentifier()->getName();
}

View File

@ -237,7 +237,7 @@ void Parser::Initialize() {
DS.StorageClassSpec = DeclSpec::SCS_typedef;
// TODO: add a 'TST_builtin' type?
DS.TypeSpecType = DeclSpec::TST_typedef;
DS.TypeSpecType = DeclSpec::TST_int;
Declarator D(DS, Declarator::FileContext);
D.SetIdentifier(PP.getIdentifierInfo("__builtin_va_list"),SourceLocation());

View File

@ -73,10 +73,18 @@ static TypeRef ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
assert(0 && "FIXME: GNU decimal extensions not supported yet!");
//DeclSpec::TST_enum:
//DeclSpec::TST_union:
//DeclSpec::TST_struct:
//DeclSpec::TST_typedef:
//case DeclSpec::TST_enum:
//case DeclSpec::TST_union:
//case DeclSpec::TST_struct:
case DeclSpec::TST_typedef: {
Decl *D = (Decl *)DS.TypenameRep;
assert(D && "Didn't get a decl for a typedef?");
// FIXME: apply type quals!
assert(DS.TypeSpecWidth == 0 && DS.TypeSpecComplex == 0 &&
DS.TypeSpecSign == 0 && DS.TypeQualifiers == 0 &&
"Can't handle qualifiers on typedef names yet!");
return Ctx.getTypeDeclType(cast<TypedefDecl>(D));
}
}
}

View File

@ -53,7 +53,10 @@ public:
/// specified element type.
TypeRef getArrayType(TypeRef EltTy, ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals, void *NumElts);
/// getTypeDeclType - Return the unique reference to the type for the
/// specified typename decl.
TypeRef getTypeDeclType(TypeDecl *Decl);
private:
void InitBuiltinTypes();

View File

@ -131,10 +131,10 @@ public:
///
/// There will be a Type object created for 'int'. Since int is canonical, its
/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a
/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next
/// TypeNameType). Its CanonicalType pointer points to the 'int' Type. Next
/// there is a PointerType that represents 'int*', which, like 'int', is
/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical
/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type
/// type is 'int*', and there is a TypeNameType for 'bar', whose canonical type
/// is also 'int*'.
///
/// Non-canonical types are useful for emitting diagnostics, without losing
@ -148,7 +148,7 @@ public:
class Type {
public:
enum TypeClass {
Builtin, Pointer, Array, Typedef
Builtin, Pointer, Array, TypeName
};
private:
Type *CanonicalType;
@ -242,13 +242,18 @@ public:
};
class TypedefType : public Type {
// Decl * here.
class TypeNameType : public Type {
TypeDecl *Decl;
TypeNameType(TypeDecl *D, Type *can) : Type(TypeName, can), Decl(D) {}
friend class ASTContext; // ASTContext creates these.
public:
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
static bool classof(const TypedefType *) { return true; }
TypeDecl *getDecl() const { return Decl; }
virtual void getAsString(std::string &InnerString) const;
static bool classof(const Type *T) { return T->getTypeClass() == TypeName; }
static bool classof(const TypeNameType *) { return true; }
};