summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
new file mode 100644
index 0000000..caa19b1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -0,0 +1,332 @@
+//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TypeLoc subclasses implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TypeLoc Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalSourceRange(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
+ if (TL.isNull()) return SourceRange();
+ return TypeLocRanger().Visit(TL);
+}
+
+namespace {
+ class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getFullDataSize(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Returns the size of the type source info data block.
+unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
+ if (Ty.isNull()) return 0;
+ return TypeSizer().Visit(TypeLoc(Ty, 0));
+}
+
+namespace {
+ class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getNextTypeLoc(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
+TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
+ return NextLoc().Visit(TL);
+}
+
+/// \brief Initializes a type location, and all of its children
+/// recursively, as if the entire tree had been written in the
+/// given location.
+void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
+ SourceLocation Loc) {
+ while (true) {
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case CLASS: { \
+ CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
+ TLCasted.initializeLocal(Context, Loc); \
+ TL = TLCasted.getNextTypeLoc(); \
+ if (!TL) return; \
+ continue; \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+}
+
+SourceLocation TypeLoc::getBeginLoc() const {
+ TypeLoc Cur = *this;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ // FIXME: Currently QualifiedTypeLoc does not have a source range
+ // case Qualified:
+ case Elaborated:
+ case DependentName:
+ case DependentTemplateSpecialization:
+ break;
+ default:
+ TypeLoc Next = Cur.getNextTypeLoc();
+ if (Next.isNull()) break;
+ Cur = Next;
+ continue;
+ }
+ break;
+ }
+ return Cur.getLocalSourceRange().getBegin();
+}
+
+SourceLocation TypeLoc::getEndLoc() const {
+ TypeLoc Cur = *this;
+ TypeLoc Last;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ default:
+ if (!Last)
+ Last = Cur;
+ return Last.getLocalSourceRange().getEnd();
+ case Paren:
+ case ConstantArray:
+ case DependentSizedArray:
+ case IncompleteArray:
+ case VariableArray:
+ case FunctionProto:
+ case FunctionNoProto:
+ Last = Cur;
+ break;
+ case Pointer:
+ case BlockPointer:
+ case MemberPointer:
+ case LValueReference:
+ case RValueReference:
+ case PackExpansion:
+ if (!Last)
+ Last = Cur;
+ break;
+ case Qualified:
+ case Elaborated:
+ break;
+ }
+ Cur = Cur.getNextTypeLoc();
+ }
+}
+
+
+namespace {
+ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class. Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+ if (TL->getType().hasLocalQualifiers()) return false;
+ return TSTChecker().Visit(*TL);
+}
+
+// Reimplemented to account for GNU/C++ extension
+// typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
+ if (getRParenLoc().isValid())
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ else
+ return SourceRange(getTypeofLoc(),
+ getUnderlyingExpr()->getSourceRange().getEnd());
+}
+
+
+TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
+ switch (getTypePtr()->getKind()) {
+ case BuiltinType::Void:
+ return TST_void;
+ case BuiltinType::Bool:
+ return TST_bool;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ return TST_char;
+ case BuiltinType::Char16:
+ return TST_char16;
+ case BuiltinType::Char32:
+ return TST_char32;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ return TST_wchar;
+ case BuiltinType::UChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::Int128:
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ llvm_unreachable("Builtin type needs extra local data!");
+ // Fall through, if the impossible happens.
+
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ case BuiltinType::BoundMember:
+ case BuiltinType::UnknownAny:
+ case BuiltinType::ARCUnbridgedCast:
+ case BuiltinType::PseudoObject:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return TST_unspecified;
+ }
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
+
+TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
+ while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
+ TL = PTL->getInnerLoc();
+ return TL;
+}
+
+void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+}
+
+void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ setNameLoc(Loc);
+}
+
+void
+DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ if (getTypePtr()->getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ } else {
+ setQualifierLoc(NestedNameSpecifierLoc());
+ }
+ setTemplateKeywordLoc(Loc);
+ setTemplateNameLoc(Loc);
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
+ getTypePtr()->getArgs(),
+ getArgInfos(), Loc);
+}
+
+void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
+ unsigned NumArgs,
+ const TemplateArgument *Args,
+ TemplateArgumentLocInfo *ArgInfos,
+ SourceLocation Loc) {
+ for (unsigned i = 0, e = NumArgs; i != e; ++i) {
+ switch (Args[i].getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Expression:
+ ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
+ break;
+
+ case TemplateArgument::Type:
+ ArgInfos[i] = TemplateArgumentLocInfo(
+ Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
+ Loc));
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
+ NestedNameSpecifierLocBuilder Builder;
+ TemplateName Template = Args[i].getAsTemplate();
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
+
+ ArgInfos[i] = TemplateArgumentLocInfo(
+ Builder.getWithLocInContext(Context),
+ Loc,
+ Args[i].getKind() == TemplateArgument::Template
+ ? SourceLocation()
+ : Loc);
+ break;
+ }
+ }
+ }
+}
OpenPOWER on IntegriCloud