diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-18 18:04:31 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-18 18:04:31 +0000 |
commit | ddf889a2ad2888f1dea573987bbe952d9912c1a0 (patch) | |
tree | 43aa47f24fb88adbd4a12ca959e103e6c27f16f6 | |
parent | 3f693d25d44d342811b2c721206a8a54f06958d5 (diff) |
Improve source-location information for builtin TypeLocs, from Enea
Zaffanella (with a couple of my tweaks).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93733 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/TypeLoc.h | 112 | ||||
-rw-r--r-- | include/clang/Basic/Specifiers.h | 72 | ||||
-rw-r--r-- | include/clang/Parse/DeclSpec.h | 85 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 56 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/DeclSpec.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 6 |
9 files changed, 333 insertions, 48 deletions
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index c36c0ffde3..0a40ea1fc4 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -16,6 +16,7 @@ #include "clang/AST/Type.h" #include "clang/AST/TemplateBase.h" +#include "clang/Basic/Specifiers.h" namespace clang { class ParmVarDecl; @@ -372,6 +373,111 @@ public: }; +struct BuiltinLocInfo { + SourceLocation BuiltinLoc; +}; + +/// \brief Wrapper for source info for builtin types. +class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + BuiltinTypeLoc, + BuiltinType, + BuiltinLocInfo> { +public: + enum { LocalDataSize = sizeof(BuiltinLocInfo) }; + + SourceLocation getBuiltinLoc() const { + return getLocalData()->BuiltinLoc; + } + void setBuiltinLoc(SourceLocation Loc) { + getLocalData()->BuiltinLoc = Loc; + } + + SourceLocation getNameLoc() const { return getBuiltinLoc(); } + + WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { + return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); + } + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { + return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); + } + + bool needsExtraLocalData() const { + BuiltinType::Kind bk = getTypePtr()->getKind(); + return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) + || (bk >= BuiltinType::Short && bk <= BuiltinType::Int128) + || bk == BuiltinType::UChar + || bk == BuiltinType::SChar; + } + + unsigned getExtraLocalDataSize() const { + return needsExtraLocalData() ? 4 : 0; + } + + SourceRange getSourceRange() const { + return SourceRange(getBuiltinLoc(), getBuiltinLoc()); + } + + TypeSpecifierSign getWrittenSignSpec() const { + if (needsExtraLocalData()) + return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign); + else + return TSS_unspecified; + } + bool hasWrittenSignSpec() const { + return getWrittenSignSpec() != TSS_unspecified; + } + void setWrittenSignSpec(TypeSpecifierSign written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Sign = written; + } + + TypeSpecifierWidth getWrittenWidthSpec() const { + if (needsExtraLocalData()) + return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width); + else + return TSW_unspecified; + } + bool hasWrittenWidthSpec() const { + return getWrittenWidthSpec() != TSW_unspecified; + } + void setWrittenWidthSpec(TypeSpecifierWidth written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Width = written; + } + + TypeSpecifierType getWrittenTypeSpec() const; + bool hasWrittenTypeSpec() const { + return getWrittenTypeSpec() != TST_unspecified; + } + void setWrittenTypeSpec(TypeSpecifierType written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Type = written; + } + + bool hasModeAttr() const { + if (needsExtraLocalData()) + return getWrittenBuiltinSpecs().ModeAttr; + else + return false; + } + void setModeAttr(bool written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().ModeAttr = written; + } + + void initializeLocal(SourceLocation Loc) { + setBuiltinLoc(Loc); + if (needsExtraLocalData()) { + WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); + wbs.Sign = TSS_unspecified; + wbs.Width = TSW_unspecified; + wbs.Type = TST_unspecified; + wbs.ModeAttr = false; + } + } +}; + + /// \brief Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, @@ -421,12 +527,6 @@ public: EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } }; -/// \brief Wrapper for source info for builtin types. -class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - BuiltinTypeLoc, - BuiltinType> { -}; - /// \brief Wrapper for template type parameters. class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h new file mode 100644 index 0000000000..68692748af --- /dev/null +++ b/include/clang/Basic/Specifiers.h @@ -0,0 +1,72 @@ +//===--- Specifiers.h - Declaration and Type Specifiers ---------*- 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 various enumerations that describe declaration and +// type specifiers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H +#define LLVM_CLANG_BASIC_SPECIFIERS_H + +namespace clang { + /// \brief Specifies the width of a type, e.g., short, long, or long long. + enum TypeSpecifierWidth { + TSW_unspecified, + TSW_short, + TSW_long, + TSW_longlong + }; + + /// \brief Specifies the signedness of a type, e.g., signed or unsigned. + enum TypeSpecifierSign { + TSS_unspecified, + TSS_signed, + TSS_unsigned + }; + + /// \brief Specifies the kind of type. + enum TypeSpecifierType { + TST_unspecified, + TST_void, + TST_char, + TST_wchar, // C++ wchar_t + TST_char16, // C++0x char16_t + TST_char32, // C++0x char32_t + TST_int, + TST_float, + TST_double, + TST_bool, // _Bool + TST_decimal32, // _Decimal32 + TST_decimal64, // _Decimal64 + TST_decimal128, // _Decimal128 + TST_enum, + TST_union, + TST_struct, + TST_class, // C++ class type + TST_typename, // Typedef, C++ class-name or enum name, etc. + TST_typeofType, + TST_typeofExpr, + TST_decltype, // C++0x decltype + TST_auto, // C++0x auto + TST_error // erroneous type + }; + + /// WrittenBuiltinSpecs - Structure that packs information about the + /// type specifiers that were written in a particular type specifier + /// sequence. + struct WrittenBuiltinSpecs { + /*DeclSpec::TST*/ unsigned Type : 5; + /*DeclSpec::TSS*/ unsigned Sign : 2; + /*DeclSpec::TSW*/ unsigned Width : 2; + bool ModeAttr : 1; + }; +} + +#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
\ No newline at end of file diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 6a3d8a924e..f923b5e910 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -17,6 +17,7 @@ #include "clang/Parse/AttributeList.h" #include "clang/Lex/Token.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -78,51 +79,50 @@ public: SCS_mutable }; - // type-specifier - enum TSW { - TSW_unspecified, - TSW_short, - TSW_long, - TSW_longlong - }; - + // Import type specifier width enumeration and constants. + typedef TypeSpecifierWidth TSW; + static const TSW TSW_unspecified = clang::TSW_unspecified; + static const TSW TSW_short = clang::TSW_short; + static const TSW TSW_long = clang::TSW_long; + static const TSW TSW_longlong = clang::TSW_longlong; + enum TSC { TSC_unspecified, TSC_imaginary, TSC_complex }; - enum TSS { - TSS_unspecified, - TSS_signed, - TSS_unsigned - }; - - enum TST { - TST_unspecified, - TST_void, - TST_char, - TST_wchar, // C++ wchar_t - TST_char16, // C++0x char16_t - TST_char32, // C++0x char32_t - TST_int, - TST_float, - TST_double, - TST_bool, // _Bool - TST_decimal32, // _Decimal32 - TST_decimal64, // _Decimal64 - TST_decimal128, // _Decimal128 - TST_enum, - TST_union, - TST_struct, - TST_class, // C++ class type - TST_typename, // Typedef, C++ class-name or enum name, etc. - TST_typeofType, - TST_typeofExpr, - TST_decltype, // C++0x decltype - TST_auto, // C++0x auto - TST_error // erroneous type - }; + // Import type specifier sign enumeration and constants. + typedef TypeSpecifierSign TSS; + static const TSS TSS_unspecified = clang::TSS_unspecified; + static const TSS TSS_signed = clang::TSS_signed; + static const TSS TSS_unsigned = clang::TSS_unsigned; + + // Import type specifier type enumeration and constants. + typedef TypeSpecifierType TST; + static const TST TST_unspecified = clang::TST_unspecified; + static const TST TST_void = clang::TST_void; + static const TST TST_char = clang::TST_char; + static const TST TST_wchar = clang::TST_wchar; + static const TST TST_char16 = clang::TST_char16; + static const TST TST_char32 = clang::TST_char32; + static const TST TST_int = clang::TST_int; + static const TST TST_float = clang::TST_float; + static const TST TST_double = clang::TST_double; + static const TST TST_bool = clang::TST_bool; + static const TST TST_decimal32 = clang::TST_decimal32; + static const TST TST_decimal64 = clang::TST_decimal64; + static const TST TST_decimal128 = clang::TST_decimal128; + static const TST TST_enum = clang::TST_enum; + static const TST TST_union = clang::TST_union; + static const TST TST_struct = clang::TST_struct; + static const TST TST_class = clang::TST_class; + static const TST TST_typename = clang::TST_typename; + static const TST TST_typeofType = clang::TST_typeofType; + static const TST TST_typeofExpr = clang::TST_typeofExpr; + static const TST TST_decltype = clang::TST_decltype; + static const TST TST_auto = clang::TST_auto; + static const TST TST_error = clang::TST_error; // type-qualifiers enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ. @@ -199,6 +199,9 @@ private: SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; SourceLocation FriendLoc, ConstexprLoc; + WrittenBuiltinSpecs writtenBS; + void SaveWrittenBuiltinSpecs(); + DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT void operator=(const DeclSpec&); // DO NOT IMPLEMENT public: @@ -411,6 +414,10 @@ public: /// DeclSpec is guaranteed self-consistent, even if an error occurred. void Finish(Diagnostic &D, Preprocessor &PP); + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { + return writtenBS; + } + /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone, /// without a Declarator. Only tag declspecs can stand alone. bool isMissingDeclaratorOk(); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 0840c52b4c..6da2ab0dee 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/raw_ostream.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/AST/Expr.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -135,3 +136,58 @@ SourceRange TypeOfExprTypeLoc::getSourceRange() const { return SourceRange(getTypeofLoc(), getUnderlyingExpr()->getSourceRange().getEnd()); } + + +TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { + if (needsExtraLocalData()) + return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); + else { + 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: + return TST_wchar; + case BuiltinType::Float: + return TST_float; + case BuiltinType::Double: + case BuiltinType::LongDouble: + return TST_double; + case BuiltinType::UndeducedAuto: + return TST_auto; + + 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: + 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::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return TST_unspecified; + } + } + + return TST_unspecified; +} diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 1f23bd2141..77fa11e3e3 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2042,7 +2042,13 @@ void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { // nothing to do } void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + if (TL.needsExtraLocalData()) { + TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++])); + TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++])); + TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++])); + TL.setModeAttr(Record[Idx++]); + } } void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 21e09744e3..97cd84f447 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -277,7 +277,13 @@ void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { // nothing to do } void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getBuiltinLoc(), Record); + if (TL.needsExtraLocalData()) { + Record.push_back(TL.getWrittenTypeSpec()); + Record.push_back(TL.getWrittenSignSpec()); + Record.push_back(TL.getWrittenWidthSpec()); + Record.push_back(TL.hasModeAttr()); + } } void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index f52d8b9856..9e5f5a2ac0 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -373,11 +373,30 @@ void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, ProtocolLAngleLoc = LAngleLoc; } +void DeclSpec::SaveWrittenBuiltinSpecs() { + writtenBS.Sign = getTypeSpecSign(); + writtenBS.Width = getTypeSpecWidth(); + writtenBS.Type = getTypeSpecType(); + // Search the list of attributes for the presence of a mode attribute. + writtenBS.ModeAttr = false; + AttributeList* attrs = getAttributes(); + while (attrs) { + if (attrs->getKind() == AttributeList::AT_mode) { + writtenBS.ModeAttr = true; + break; + } + attrs = attrs->getNext(); + } +} + /// Finish - This does final analysis of the declspec, rejecting things like /// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or /// diag::NUM_DIAGNOSTICS if there is no error. After calling this method, /// DeclSpec is guaranteed self-consistent, even if an error occurred. void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) { + // Before possibly changing their values, save specs as written. + SaveWrittenBuiltinSpecs(); + // Check the type specifier components first. SourceManager &SrcMgr = PP.getSourceManager(); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9515834bb8..906576115a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1374,6 +1374,21 @@ namespace { Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo); TL.setUnderlyingTInfo(TInfo); } + void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { + // By default, use the source location of the type specifier. + TL.setBuiltinLoc(DS.getTypeSpecTypeLoc()); + if (TL.needsExtraLocalData()) { + // Set info for the written builtin specifiers. + TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs(); + // Try to have a meaningful source location. + if (TL.getWrittenSignSpec() != TSS_unspecified) + // Sign spec loc overrides the others (e.g., 'unsigned long'). + TL.setBuiltinLoc(DS.getTypeSpecSignLoc()); + else if (TL.getWrittenWidthSpec() != TSW_unspecified) + // Width spec loc overrides type spec loc (e.g., 'short int'). + TL.setBuiltinLoc(DS.getTypeSpecWidthLoc()); + } + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. TL.initialize(DS.getTypeSpecTypeLoc()); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 41f465f595..aba6455df3 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2138,7 +2138,11 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { template<typename Derived> QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB, BuiltinTypeLoc T) { - return TransformTypeSpecType(TLB, T); + BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType()); + NewT.setBuiltinLoc(T.getBuiltinLoc()); + if (T.needsExtraLocalData()) + NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs(); + return T.getType(); } template<typename Derived> |