Build ASTs for the pointer qualifiers on declarators. This allows us to

parse (and print) things like:

int* const* restrict* const volatile***

etc.

llvm-svn: 39173
This commit is contained in:
Chris Lattner 2006-11-12 00:37:36 +00:00
parent aecbefa519
commit 970e54e3ac
8 changed files with 153 additions and 125 deletions

View File

@ -12,12 +12,62 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/Lex/Preprocessor.h"
using namespace llvm;
using namespace clang;
ASTContext::ASTContext(Preprocessor &pp)
: PP(pp), Target(pp.getTargetInfo()) {
InitBuiltinTypes();
}
void ASTContext::InitBuiltinTypes() {
assert(VoidTy.isNull() && "Context reinitialized?");
// C99 6.2.5p19.
Types.push_back(VoidTy = new BuiltinType("void"));
// C99 6.2.5p2.
Types.push_back(BoolTy = new BuiltinType("_Bool"));
// C99 6.2.5p3.
Types.push_back(CharTy = new BuiltinType("char"));
// C99 6.2.5p4.
Types.push_back(SignedCharTy = new BuiltinType("signed char"));
Types.push_back(ShortTy = new BuiltinType("short"));
Types.push_back(IntTy = new BuiltinType("int"));
Types.push_back(LongTy = new BuiltinType("long"));
Types.push_back(LongLongTy = new BuiltinType("long long"));
// C99 6.2.5p6.
Types.push_back(UnsignedCharTy = new BuiltinType("unsigned char"));
Types.push_back(UnsignedShortTy = new BuiltinType("unsigned short"));
Types.push_back(UnsignedIntTy = new BuiltinType("unsigned int"));
Types.push_back(UnsignedLongTy = new BuiltinType("unsigned long"));
Types.push_back(UnsignedLongLongTy = new BuiltinType("unsigned long long"));
// C99 6.2.5p10.
Types.push_back(FloatTy = new BuiltinType("float"));
Types.push_back(DoubleTy = new BuiltinType("double"));
Types.push_back(LongDoubleTy = new BuiltinType("long double"));
// C99 6.2.5p11.
Types.push_back(FloatComplexTy = new BuiltinType("float _Complex"));
Types.push_back(DoubleComplexTy = new BuiltinType("double _Complex"));
Types.push_back(LongDoubleComplexTy= new BuiltinType("long double _Complex"));
}
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
TypeRef ASTContext::getPointerType(const TypeRef &T) {
// FIXME: memoize these.
Type *Canonical = 0;
if (!T->isCanonical())
Canonical = getPointerType(T.getCanonicalType()).getTypePtr();
return new PointerType(T, Canonical);
}

View File

@ -38,7 +38,6 @@ class Sema : public Action {
public:
Sema(ASTContext &ctx, std::vector<Decl*> &prevInGroup)
: Context(ctx), LastInGroupList(prevInGroup) {
InitializeBuiltinTypes();
}
void Diag(SourceLocation Loc, unsigned DiagID,
@ -47,7 +46,6 @@ public:
//===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp.
//
void InitializeBuiltinTypes();
TypeRef GetTypeForDeclarator(Declarator &D, Scope *S);

View File

@ -17,61 +17,6 @@
using namespace llvm;
using namespace clang;
namespace {
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
const char *Name;
public:
BuiltinType(const char *name) : Name(name) {}
virtual void dump() const;
};
}
// FIXME: REMOVE
#include <iostream>
void BuiltinType::dump() const {
std::cerr << Name;
}
void Sema::InitializeBuiltinTypes() {
assert(Context.VoidTy.isNull() && "Context reinitialized?");
// C99 6.2.5p19.
Context.VoidTy = new BuiltinType("void");
// C99 6.2.5p2.
Context.BoolTy = new BuiltinType("_Bool");
// C99 6.2.5p3.
Context.CharTy = new BuiltinType("char");
// C99 6.2.5p4.
Context.SignedCharTy = new BuiltinType("signed char");
Context.ShortTy = new BuiltinType("short");
Context.IntTy = new BuiltinType("int");
Context.LongTy = new BuiltinType("long");
Context.LongLongTy = new BuiltinType("long long");
// C99 6.2.5p6.
Context.UnsignedCharTy = new BuiltinType("unsigned char");
Context.UnsignedShortTy = new BuiltinType("unsigned short");
Context.UnsignedIntTy = new BuiltinType("unsigned int");
Context.UnsignedLongTy = new BuiltinType("unsigned long");
Context.UnsignedLongLongTy = new BuiltinType("unsigned long long");
// C99 6.2.5p10.
Context.FloatTy = new BuiltinType("float");
Context.DoubleTy = new BuiltinType("double");
Context.LongDoubleTy = new BuiltinType("long double");
// C99 6.2.5p11.
Context.FloatComplexTy = new BuiltinType("float _Complex");
Context.DoubleComplexTy = new BuiltinType("double _Complex");
Context.LongDoubleComplexTy = new BuiltinType("long double _Complex");
}
/// ConvertDeclSpecToType - Convert the specified declspec to the appropriate
/// type object. This returns null on error.
static TypeRef ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
@ -142,6 +87,22 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
// Apply const/volatile/restrict qualifiers to T.
T = T.getQualifiedType(D.getDeclSpec().TypeQualifiers);
// Walk the DeclTypeInfo, building the recursive type as we go.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
const DeclaratorTypeInfo &DeclType = D.getTypeObject(e-i-1);
switch (DeclType.Kind) {
default: assert(0 && "Unknown decltype!");
case DeclaratorTypeInfo::Pointer:
T = Context.getPointerType(T);
// Apply the pointer typequals to the pointer object.
T = T.getQualifiedType(DeclType.Ptr.TypeQuals);
break;
case DeclaratorTypeInfo::Array:
case DeclaratorTypeInfo::Function:
return TypeRef(); // FIXME: implement these!
}
}
return T;
return TypeRef();
}

View File

@ -12,28 +12,53 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Type.h"
#include <iostream>
using namespace llvm;
using namespace clang;
Type::~Type() {}
//===----------------------------------------------------------------------===//
// Type Construction
//===----------------------------------------------------------------------===//
PointerType::PointerType(TypeRef Pointee, Type *Canonical)
: Type(Canonical), PointeeType(Pointee) {
}
//===----------------------------------------------------------------------===//
// Type Printing
//===----------------------------------------------------------------------===//
#include <iostream> // FIXME: REMOVE
void TypeRef::dump() const {
print(std::cerr);
std::cerr << "\n";
}
void TypeRef::print(std::ostream &OS) const {
if (isNull()) {
std::cerr << "NULL TYPE\n";
OS << "NULL TYPE\n";
return;
}
(*this)->dump();
getTypePtr()->print(OS);
// Print qualifiers as appropriate.
if (isConstQualified())
std::cerr << " const";
OS << " const";
if (isVolatileQualified())
std::cerr << " volatile";
OS << " volatile";
if (isRestrictQualified())
std::cerr << " restrict";
std::cerr << "\n";
OS << " restrict";
}
void BuiltinType::print(std::ostream &OS) const {
OS << Name;
}
void PointerType::print(std::ostream &OS) const {
PointeeType.print(OS);
OS << "*";
}

View File

@ -38,7 +38,6 @@ class Sema : public Action {
public:
Sema(ASTContext &ctx, std::vector<Decl*> &prevInGroup)
: Context(ctx), LastInGroupList(prevInGroup) {
InitializeBuiltinTypes();
}
void Diag(SourceLocation Loc, unsigned DiagID,
@ -47,7 +46,6 @@ public:
//===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp.
//
void InitializeBuiltinTypes();
TypeRef GetTypeForDeclarator(Declarator &D, Scope *S);

View File

@ -17,61 +17,6 @@
using namespace llvm;
using namespace clang;
namespace {
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
const char *Name;
public:
BuiltinType(const char *name) : Name(name) {}
virtual void dump() const;
};
}
// FIXME: REMOVE
#include <iostream>
void BuiltinType::dump() const {
std::cerr << Name;
}
void Sema::InitializeBuiltinTypes() {
assert(Context.VoidTy.isNull() && "Context reinitialized?");
// C99 6.2.5p19.
Context.VoidTy = new BuiltinType("void");
// C99 6.2.5p2.
Context.BoolTy = new BuiltinType("_Bool");
// C99 6.2.5p3.
Context.CharTy = new BuiltinType("char");
// C99 6.2.5p4.
Context.SignedCharTy = new BuiltinType("signed char");
Context.ShortTy = new BuiltinType("short");
Context.IntTy = new BuiltinType("int");
Context.LongTy = new BuiltinType("long");
Context.LongLongTy = new BuiltinType("long long");
// C99 6.2.5p6.
Context.UnsignedCharTy = new BuiltinType("unsigned char");
Context.UnsignedShortTy = new BuiltinType("unsigned short");
Context.UnsignedIntTy = new BuiltinType("unsigned int");
Context.UnsignedLongTy = new BuiltinType("unsigned long");
Context.UnsignedLongLongTy = new BuiltinType("unsigned long long");
// C99 6.2.5p10.
Context.FloatTy = new BuiltinType("float");
Context.DoubleTy = new BuiltinType("double");
Context.LongDoubleTy = new BuiltinType("long double");
// C99 6.2.5p11.
Context.FloatComplexTy = new BuiltinType("float _Complex");
Context.DoubleComplexTy = new BuiltinType("double _Complex");
Context.LongDoubleComplexTy = new BuiltinType("long double _Complex");
}
/// ConvertDeclSpecToType - Convert the specified declspec to the appropriate
/// type object. This returns null on error.
static TypeRef ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
@ -142,6 +87,22 @@ TypeRef Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
// Apply const/volatile/restrict qualifiers to T.
T = T.getQualifiedType(D.getDeclSpec().TypeQualifiers);
// Walk the DeclTypeInfo, building the recursive type as we go.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
const DeclaratorTypeInfo &DeclType = D.getTypeObject(e-i-1);
switch (DeclType.Kind) {
default: assert(0 && "Unknown decltype!");
case DeclaratorTypeInfo::Pointer:
T = Context.getPointerType(T);
// Apply the pointer typequals to the pointer object.
T = T.getQualifiedType(DeclType.Ptr.TypeQuals);
break;
case DeclaratorTypeInfo::Array:
case DeclaratorTypeInfo::Function:
return TypeRef(); // FIXME: implement these!
}
}
return T;
return TypeRef();
}

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_ASTCONTEXT_H
#include "clang/AST/Type.h"
#include <vector>
namespace llvm {
namespace clang {
@ -24,6 +25,8 @@ namespace clang {
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
// FIXME: This is a stupid data structure.
std::vector<TypeRef> Types;
public:
Preprocessor &PP;
TargetInfo &Target;
@ -42,7 +45,12 @@ public:
ASTContext(Preprocessor &pp);
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
TypeRef getPointerType(const TypeRef &T);
private:
void InitBuiltinTypes();
};
} // end namespace clang

View File

@ -16,9 +16,11 @@
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <iosfwd>
namespace llvm {
namespace clang {
class ASTContext;
class TypeDecl;
class Type;
@ -89,7 +91,11 @@ public:
return TypeRef(getTypePtr());
}
/// getCanonicalType - Return the canonical version of this type, with the
/// appropriate type qualifiers on it.
inline TypeRef getCanonicalType() const;
void print(std::ostream &OS) const;
void dump() const;
};
@ -122,18 +128,32 @@ public:
class Type {
Type *CanonicalType;
public:
Type(Type *Canonical) : CanonicalType(Canonical ? Canonical : this) {}
virtual ~Type();
bool isCanonical() const { return CanonicalType == this; }
Type *getCanonicalType() const { return CanonicalType; }
virtual void dump() const = 0;
virtual void print(std::ostream &OS) const = 0;
};
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
const char *Name;
public:
BuiltinType(const char *name) : Type(0), Name(name) {}
virtual void print(std::ostream &OS) const;
};
class PointerType : public Type {
TypeRef PointeeType;
PointerType(TypeRef Pointee, Type *CanonicalPtr = 0);
friend class ASTContext; // ASTContext creates these.
public:
virtual void print(std::ostream &OS) const;
};
class TypedefType : public Type {
@ -151,6 +171,13 @@ public:
// specify the same type, we want to print the default argument only if
// specified in the source code.
/// getCanonicalType - Return the canonical version of this type, with the
/// appropriate type qualifiers on it.
inline TypeRef TypeRef::getCanonicalType() const {
return TypeRef(getTypePtr()->getCanonicalType(), getQualifiers());
}
} // end namespace clang
} // end namespace llvm