From ddf889a2ad2888f1dea573987bbe952d9912c1a0 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 18 Jan 2010 18:04:31 +0000 Subject: [PATCH] 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 --- include/clang/AST/TypeLoc.h | 112 +++++++++++++++++++++++++++++-- include/clang/Basic/Specifiers.h | 72 ++++++++++++++++++++ include/clang/Parse/DeclSpec.h | 85 ++++++++++++----------- lib/AST/TypeLoc.cpp | 56 ++++++++++++++++ lib/Frontend/PCHReader.cpp | 8 ++- lib/Frontend/PCHWriter.cpp | 8 ++- lib/Parse/DeclSpec.cpp | 19 ++++++ lib/Sema/SemaType.cpp | 15 +++++ lib/Sema/TreeTransform.h | 6 +- 9 files changed, 333 insertions(+), 48 deletions(-) create mode 100644 include/clang/Basic/Specifiers.h 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 { +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(getExtraLocalData())); + } + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { + return *(static_cast(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(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(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 InheritingConcreteTypeLocgetDecl(); } }; -/// \brief Wrapper for source info for builtin types. -class BuiltinTypeLoc : public InheritingConcreteTypeLoc { -}; - /// \brief Wrapper for template type parameters. class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLocgetSourceRange().getEnd()); } + + +TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { + if (needsExtraLocalData()) + return static_cast(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(Record[Idx++])); + TL.setWrittenSignSpec(static_cast(Record[Idx++])); + TL.setWrittenWidthSpec(static_cast(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 QualType TreeTransform::TransformBuiltinType(TypeLocBuilder &TLB, BuiltinTypeLoc T) { - return TransformTypeSpecType(TLB, T); + BuiltinTypeLoc NewT = TLB.push(T.getType()); + NewT.setBuiltinLoc(T.getBuiltinLoc()); + if (T.needsExtraLocalData()) + NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs(); + return T.getType(); } template -- 2.40.0