forked from OSchip/llvm-project
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:
parent
aecbefa519
commit
970e54e3ac
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 << "*";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue