From cac9896ed787350386daa98be57b98d77f21d0a7 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 1 Jul 2025 11:51:04 +0200 Subject: [PATCH 01/15] [clang] Don't use raw source location in DeclarationName, NFC (#146412) Converting back and forth for the source location raw encoding is unnecessary. --- clang/include/clang/AST/DeclarationName.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/AST/DeclarationName.h b/clang/include/clang/AST/DeclarationName.h index 9bf740b3bf7ce..284228dc0ee47 100644 --- a/clang/include/clang/AST/DeclarationName.h +++ b/clang/include/clang/AST/DeclarationName.h @@ -698,13 +698,13 @@ class DeclarationNameLoc { // The location (if any) of the operator keyword is stored elsewhere. struct CXXOpName { - SourceLocation::UIntTy BeginOpNameLoc; - SourceLocation::UIntTy EndOpNameLoc; + SourceLocation BeginOpNameLoc; + SourceLocation EndOpNameLoc; }; // The location (if any) of the operator keyword is stored elsewhere. struct CXXLitOpName { - SourceLocation::UIntTy OpNameLoc; + SourceLocation OpNameLoc; }; // struct {} CXXUsingDirective; @@ -720,12 +720,12 @@ class DeclarationNameLoc { void setNamedTypeLoc(TypeSourceInfo *TInfo) { NamedType.TInfo = TInfo; } void setCXXOperatorNameRange(SourceRange Range) { - CXXOperatorName.BeginOpNameLoc = Range.getBegin().getRawEncoding(); - CXXOperatorName.EndOpNameLoc = Range.getEnd().getRawEncoding(); + CXXOperatorName.BeginOpNameLoc = Range.getBegin(); + CXXOperatorName.EndOpNameLoc = Range.getEnd(); } void setCXXLiteralOperatorNameLoc(SourceLocation Loc) { - CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); + CXXLiteralOperatorName.OpNameLoc = Loc; } public: @@ -739,12 +739,12 @@ class DeclarationNameLoc { /// Return the beginning location of the getCXXOperatorNameRange() range. SourceLocation getCXXOperatorNameBeginLoc() const { - return SourceLocation::getFromRawEncoding(CXXOperatorName.BeginOpNameLoc); + return CXXOperatorName.BeginOpNameLoc; } /// Return the end location of the getCXXOperatorNameRange() range. SourceLocation getCXXOperatorNameEndLoc() const { - return SourceLocation::getFromRawEncoding(CXXOperatorName.EndOpNameLoc); + return CXXOperatorName.EndOpNameLoc; } /// Return the range of the operator name (without the operator keyword). @@ -759,7 +759,7 @@ class DeclarationNameLoc { /// keyword). Assumes that the object stores location information of a literal /// operator. SourceLocation getCXXLiteralOperatorNameLoc() const { - return SourceLocation::getFromRawEncoding(CXXLiteralOperatorName.OpNameLoc); + return CXXLiteralOperatorName.OpNameLoc; } /// Construct location information for a constructor, destructor or conversion From 5a3d88c9fb260166749ee2bebd622d3c4acf9e6e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 1 Jul 2025 22:32:32 +0200 Subject: [PATCH 02/15] [Serialization] Use SourceLocation::UIntTy for the offset type, NFC --- clang/lib/Serialization/ASTWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 06cd6c7305114..874b24b532b06 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6652,7 +6652,7 @@ void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) { SourceLocationEncoding::RawLocEncoding ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc) { - unsigned BaseOffset = 0; + SourceLocation::UIntTy BaseOffset = 0; unsigned ModuleFileIndex = 0; // See SourceLocationEncoding.h for the encoding details. From 808b37112c5a17444a21fb579dc7d57b91b97fa5 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 2 Jul 2025 09:09:26 +0200 Subject: [PATCH 03/15] [Serialization] Use the SourceLocation::UIntTy instead of the raw type for the offset, NFC --- clang/include/clang/Serialization/ASTReader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 7d4b4467eb97d..43b4576093cf4 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -525,7 +525,7 @@ class ASTReader ContinuousRangeMap GlobalSLocEntryMap; using GlobalSLocOffsetMapType = - ContinuousRangeMap; + ContinuousRangeMap; /// A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset) /// SourceLocation offsets to the modules containing them. From 1fdaa67bf716a78ce84c90f9077cc93c2a6cb0b1 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 7 Jul 2025 14:15:25 +0200 Subject: [PATCH 04/15] [clang] Remove source range from CXXOperatorCallExpr (#147028) This patch stops storing a source range in `CXXOperatorCallExpr` and keeps only the begin location. This change allows us to retain the optimization #141058 when switching to 64-bit source locations. Performance results: https://llvm-compile-time-tracker.com/compare.php?from=0588e8188c647460b641b09467fe6b13a8d510d5&to=5958f83476a8b8ba97936f262396d3ff98fb1662&stat=instructions:u --- clang/include/clang/AST/ExprCXX.h | 8 ++++---- clang/lib/AST/ExprCXX.cpp | 2 +- clang/lib/Serialization/ASTReaderStmt.cpp | 2 +- clang/lib/Serialization/ASTWriterDecl.cpp | 1 - clang/lib/Serialization/ASTWriterStmt.cpp | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 477373f07f25d..a22c32241ac61 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -84,7 +84,7 @@ class CXXOperatorCallExpr final : public CallExpr { friend class ASTStmtReader; friend class ASTStmtWriter; - SourceRange Range; + SourceLocation BeginLoc; // CXXOperatorCallExpr has some trailing objects belonging // to CallExpr. See CallExpr for the details. @@ -158,9 +158,9 @@ class CXXOperatorCallExpr final : public CallExpr { : getOperatorLoc(); } - SourceLocation getBeginLoc() const { return Range.getBegin(); } - SourceLocation getEndLoc() const { return Range.getEnd(); } - SourceRange getSourceRange() const { return Range; } + SourceLocation getBeginLoc() const { return BeginLoc; } + SourceLocation getEndLoc() const { return getSourceRangeImpl().getEnd(); } + SourceRange getSourceRange() const { return getSourceRangeImpl(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 063eb1738a046..685ef8baa70a3 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -600,7 +600,7 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind, assert( (CXXOperatorCallExprBits.OperatorKind == static_cast(OpKind)) && "OperatorKind overflow!"); - Range = getSourceRangeImpl(); + BeginLoc = getSourceRangeImpl().getBegin(); } CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8945407cf666e..0166e493bf03f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1733,7 +1733,7 @@ void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); E->CXXOperatorCallExprBits.OperatorKind = Record.readInt(); - E->Range = Record.readSourceRange(); + E->BeginLoc = Record.readSourceLocation(); } void ASTStmtReader::VisitCXXRewrittenBinaryOperator( diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 2e390dbe79ec6..a5c81036d6d43 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2935,7 +2935,6 @@ void ASTWriter::WriteDeclAbbrevs() { // CXXOperatorCallExpr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Operator Kind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location CXXOperatorCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for EXPR_CXX_MEMBER_CALL diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 87536be8c8d98..be9bad9e96cc1 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1702,7 +1702,7 @@ void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) { void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); - Record.AddSourceRange(E->Range); + Record.AddSourceLocation(E->BeginLoc); if (!E->hasStoredFPFeatures() && !static_cast(E->getADLCallKind())) AbbrevToUse = Writer.getCXXOperatorCallExprAbbrev(); From 6c401d45ef9705b951da82f43cf9ee90ed6e94ee Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 7 May 2025 21:47:32 +0200 Subject: [PATCH 05/15] 64-bit source location fix Reduce the Stmt size back to 8 bytes. Reduce the CallExpr size Fix the ObjCContainerDecl bit field Change the SourceLocation::UIntTy to uint64_t Update other SourceManager's getDecomposedSpellingLoc APIs, and fix many failing tests. Remaining failures: Clang :: Index/IBOutletCollection.m Clang :: Index/annotate-macro-args.m Clang :: Index/annotate-module.m Clang :: Index/annotate-tokens-pp.c Clang :: Index/annotate-tokens.c Clang :: Index/annotate-toplevel-in-objccontainer.m Clang :: Index/hidden-redecls.m Clang :: Index/index-module-with-vfs.m Clang :: Index/index-module.m Clang :: Index/index-pch-objc.m Clang :: Index/index-pch-with-module.m Clang :: Index/index-pch.cpp Clang :: Index/targeted-annotation.c Clang :: Lexer/SourceLocationsOverflow.c Clang-Unit :: ./AllClangUnitTests/PPMemoryAllocationsTest/PPMacroDefinesAllocations Clang-Unit :: ./AllClangUnitTests/SourceLocationEncoding/Individual Clang-Unit :: ./AllClangUnitTests/SourceLocationEncoding/Sequence Clang-Unit :: libclang/./libclangTests/14/53 Clang-Unit :: libclang/./libclangTests/45/53 Clang-Unit :: libclang/./libclangTests/47/53 Clang-Unit :: libclang/./libclangTests/48/53 Clang-Unit :: libclang/./libclangTests/49/53 Clang-Unit :: libclang/./libclangTests/50/53 Clang-Unit :: libclang/./libclangTests/52/53 Fix libclang failures Fix Rewrite APIs Fix PPMemoryAllocationsTest Fix SourceLocationEncodingTest More unsigned -> SourceLocation::UIntTy changes in the SourceManager APIs Update the type of std::pair in CIndex.cpp Fix SourceLocationEncodingTest Tweak the SourceLocation Implementation. The source location has a Bit which specify the number of bits used for the offset. 40 by default; Make MathExtra templates constexpr Test Bits=64 perf Try 48 bits No bitfields Fix CallExpr optimization. Test Bits=64 perf Switch Bits back to 40. Reduce SubstNonTypeTemplateParmExpr size: 48 -> 40 bytes Reduce OpaqueValueExpr: 32 -> 24 bytes Reduce CXXDependentScopeMemberExpr size: 88 -> 80 bytes Reduce DeclRefExpr size: 48 -> 40 bytes. by moving out the two source locations for CXXOpName from DeclarationNameLoc Fix some merge conflicts. Move the Loc back to the StmtBitFields if possible to save AST size. Improve getFildIDLocal binary search. Optimize binary search by using a dedicate offset table improve the cache performance Revert the static_assert change for ObjCContainerDeclBitfields. Fix the compile failures for include-cleaner. Fix clang-tidy build. Fix clangd unittest Fix windows build failures. unsigned long is 32 bits on MSVC More windows fix Change the underlying StmtBitField type to uint64_t, fix windows failures. So that the sizeof(Stmt) can stay with 8 bytes. More window fix Fix merge failures Update comments for SourceLocation. clang-format revert the Rewrite change. Don't change the FileIDAndOffset type. Revert the change in ObjCContainerDeclBitfields Revert the changei n HTMLReport.cpp Revert the unsigned -> UIntTy change in Diagnostic.h Revert the unsigned->UIntTy change in SourceManager. revert the binary optimization change. clang-format More cleanup Cleanup some unnecessary change. Get rid of the Range in CXXOperatorCallExpr. revert unintentional changes. Remove unintentional change. Revert unintentional changes. --- .../FunctionCognitiveComplexityCheck.cpp | 4 +- .../clangd/unittests/SourceCodeTests.cpp | 4 +- clang/include/clang/AST/ASTContext.h | 2 + clang/include/clang/AST/DeclBase.h | 10 +- clang/include/clang/AST/DeclObjC.h | 6 +- clang/include/clang/AST/DeclarationName.h | 46 ++- clang/include/clang/AST/Expr.h | 66 ++-- clang/include/clang/AST/ExprCXX.h | 73 ++-- clang/include/clang/AST/ExprConcepts.h | 5 +- clang/include/clang/AST/ExternalASTSource.h | 2 +- clang/include/clang/AST/Stmt.h | 337 +++++++++++------- clang/include/clang/Basic/SourceLocation.h | 28 +- clang/include/clang/Basic/SourceManager.h | 6 +- .../clang/Sema/MultiplexExternalSemaSource.h | 2 +- .../include/clang/Serialization/ASTBitCodes.h | 4 +- .../Serialization/SourceLocationEncoding.h | 33 +- clang/lib/AST/ASTContext.cpp | 11 +- clang/lib/AST/ASTImporter.cpp | 3 +- clang/lib/AST/DeclarationName.cpp | 2 +- clang/lib/AST/Expr.cpp | 31 +- clang/lib/AST/ExprCXX.cpp | 6 +- clang/lib/AST/ExprConcepts.cpp | 2 +- clang/lib/AST/ExternalASTSource.cpp | 2 +- clang/lib/AST/Stmt.cpp | 2 +- clang/lib/Basic/SourceLocation.cpp | 38 ++ clang/lib/CodeGen/CoverageMappingGen.cpp | 3 +- clang/lib/Format/FormatTokenLexer.cpp | 3 +- clang/lib/Lex/Lexer.cpp | 7 +- clang/lib/Parse/ParseStmtAsm.cpp | 3 +- .../lib/Sema/MultiplexExternalSemaSource.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 13 +- clang/lib/Sema/SemaLambda.cpp | 4 +- clang/lib/Sema/SemaOverload.cpp | 9 +- clang/lib/Serialization/ASTReader.cpp | 3 +- clang/lib/Serialization/ASTReaderStmt.cpp | 31 +- clang/lib/Serialization/ASTWriterDecl.cpp | 2 +- clang/lib/Serialization/ASTWriterStmt.cpp | 2 +- clang/test/Lexer/SourceLocationsOverflow.c | 38 -- clang/tools/libclang/CIndex.cpp | 72 ++-- clang/tools/libclang/CXIndexDataConsumer.cpp | 10 +- clang/tools/libclang/CXSourceLocation.cpp | 69 ++-- clang/tools/libclang/CXSourceLocation.h | 24 +- clang/tools/libclang/Indexing.cpp | 25 +- .../unittests/Lex/PPMemoryAllocationsTest.cpp | 2 +- .../SourceLocationEncodingTest.cpp | 3 + 45 files changed, 639 insertions(+), 411 deletions(-) delete mode 100644 clang/test/Lexer/SourceLocationsOverflow.c diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp index e1fb42b8210e2..ecde1f7c90080 100644 --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp @@ -127,12 +127,12 @@ struct CognitiveComplexity final { // https://sonarcloud.io/projects?languages=c%2Ccpp&size=5 we can estimate: // value ~20 would result in no allocs for 98% of functions, ~12 for 96%, ~10 // for 91%, ~8 for 88%, ~6 for 84%, ~4 for 77%, ~2 for 64%, and ~1 for 37%. - static_assert(sizeof(Detail) <= 8, + static_assert(sizeof(Detail) <= 16, "Since we use SmallVector to minimize the amount of " "allocations, we also need to consider the price we pay for " "that in terms of stack usage. " "Thus, it is good to minimize the size of the Detail struct."); - SmallVector Details; // 25 elements is 200 bytes. + SmallVector Details; // 25 elements is 400 bytes. // Yes, 25 is a magic number. This is the seemingly-sane default for the // upper limit for function cognitive complexity. Thus it would make sense // to avoid allocations for any function that does not violate the limit. diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp index 801d535c1b9d0..931241845c54a 100644 --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -829,7 +829,9 @@ TEST(SourceCodeTests, isSpelledInSource) { // FIXME: Should it return false on SourceLocation()? Does it matter? EXPECT_TRUE(isSpelledInSource(SourceLocation(), SM)); EXPECT_FALSE(isSpelledInSource( - SourceLocation::getFromRawEncoding(SourceLocation::UIntTy(1 << 31)), SM)); + SourceLocation::getFromRawEncoding( + SourceLocation::UIntTy(1ULL << (SourceLocation::Bits - 1))), + SM)); } struct IncrementalTestStep { diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2b9cd035623cc..8ae212cc6cc94 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3356,6 +3356,8 @@ class ASTContext : public RefCountedBase { getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()) const; + CXXOperatorSourceInfo *getCXXOperatorSourceInfo(SourceRange R) const; + /// Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index dd67ebc9873ff..a76d54ccd8387 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1952,17 +1952,13 @@ class DeclContext { friend class ObjCContainerDecl; /// For the bits in DeclContextBitfields LLVM_PREFERRED_TYPE(DeclContextBitfields) - uint32_t : NumDeclContextBits; + uint64_t : NumDeclContextBits; - // Not a bitfield but this saves space. - // Note that ObjCContainerDeclBitfields is full. - SourceLocation AtStart; + uint64_t AtStart : SourceLocation::Bits; }; /// Number of inherited and non-inherited bits in ObjCContainerDeclBitfields. - /// Note that here we rely on the fact that SourceLocation is 32 bits - /// wide. We check this with the static_assert in the ctor of DeclContext. - enum { NumObjCContainerDeclBits = 64 }; + enum { NumObjCContainerDeclBits = NumDeclContextBits + SourceLocation::Bits }; /// Stores the bits used by LinkageSpecDecl. /// If modified NumLinkageSpecDeclBits and the accessor diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 9014d76f8433b..794059012ae9e 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1090,10 +1090,12 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext { /// Note, the superclass's properties are not included in the list. virtual void collectPropertiesToImplement(PropertyMap &PM) const {} - SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; } + SourceLocation getAtStartLoc() const { + return SourceLocation::getFromRawEncoding(ObjCContainerDeclBits.AtStart); + } void setAtStartLoc(SourceLocation Loc) { - ObjCContainerDeclBits.AtStart = Loc; + ObjCContainerDeclBits.AtStart = Loc.getRawEncoding(); } // Marks the end of the container. diff --git a/clang/include/clang/AST/DeclarationName.h b/clang/include/clang/AST/DeclarationName.h index 284228dc0ee47..bbb91fc14fdce 100644 --- a/clang/include/clang/AST/DeclarationName.h +++ b/clang/include/clang/AST/DeclarationName.h @@ -682,6 +682,11 @@ class DeclarationNameTable { DeclarationName getCXXLiteralOperatorName(const IdentifierInfo *II); }; +struct CXXOperatorSourceInfo { + SourceLocation BeginOpNameLoc; + SourceLocation EndOpNameLoc; +}; + /// DeclarationNameLoc - Additional source/type location info /// for a declaration name. Needs a DeclarationName in order /// to be interpreted correctly. @@ -698,8 +703,7 @@ class DeclarationNameLoc { // The location (if any) of the operator keyword is stored elsewhere. struct CXXOpName { - SourceLocation BeginOpNameLoc; - SourceLocation EndOpNameLoc; + CXXOperatorSourceInfo *OInfo; }; // The location (if any) of the operator keyword is stored elsewhere. @@ -719,11 +723,6 @@ class DeclarationNameLoc { void setNamedTypeLoc(TypeSourceInfo *TInfo) { NamedType.TInfo = TInfo; } - void setCXXOperatorNameRange(SourceRange Range) { - CXXOperatorName.BeginOpNameLoc = Range.getBegin(); - CXXOperatorName.EndOpNameLoc = Range.getEnd(); - } - void setCXXLiteralOperatorNameLoc(SourceLocation Loc) { CXXLiteralOperatorName.OpNameLoc = Loc; } @@ -739,12 +738,16 @@ class DeclarationNameLoc { /// Return the beginning location of the getCXXOperatorNameRange() range. SourceLocation getCXXOperatorNameBeginLoc() const { - return CXXOperatorName.BeginOpNameLoc; + if (!CXXOperatorName.OInfo) + return {}; + return CXXOperatorName.OInfo->BeginOpNameLoc; } /// Return the end location of the getCXXOperatorNameRange() range. SourceLocation getCXXOperatorNameEndLoc() const { - return CXXOperatorName.EndOpNameLoc; + if (!CXXOperatorName.OInfo) + return {}; + return CXXOperatorName.OInfo->EndOpNameLoc; } /// Return the range of the operator name (without the operator keyword). @@ -771,15 +774,10 @@ class DeclarationNameLoc { } /// Construct location information for a non-literal C++ operator. - static DeclarationNameLoc makeCXXOperatorNameLoc(SourceLocation BeginLoc, - SourceLocation EndLoc) { - return makeCXXOperatorNameLoc(SourceRange(BeginLoc, EndLoc)); - } - - /// Construct location information for a non-literal C++ operator. - static DeclarationNameLoc makeCXXOperatorNameLoc(SourceRange Range) { + static DeclarationNameLoc + makeCXXOperatorNameLoc(CXXOperatorSourceInfo *OInfo) { DeclarationNameLoc DNL; - DNL.setCXXOperatorNameRange(Range); + DNL.CXXOperatorName.OInfo = OInfo; return DNL; } @@ -849,6 +847,13 @@ struct DeclarationNameInfo { LocInfo = DeclarationNameLoc::makeNamedTypeLoc(TInfo); } + /// Sets the range of the operator name (without the operator keyword). + /// Assumes it is a C++ operator. + void setCXXOperatorNameInfo(CXXOperatorSourceInfo *OInfo) { + assert(Name.getNameKind() == DeclarationName::CXXOperatorName); + LocInfo = DeclarationNameLoc::makeCXXOperatorNameLoc(OInfo); + } + /// getCXXOperatorNameRange - Gets the range of the operator name /// (without the operator keyword). Assumes it is a (non-literal) operator. SourceRange getCXXOperatorNameRange() const { @@ -857,13 +862,6 @@ struct DeclarationNameInfo { return LocInfo.getCXXOperatorNameRange(); } - /// setCXXOperatorNameRange - Sets the range of the operator name - /// (without the operator keyword). Assumes it is a C++ operator. - void setCXXOperatorNameRange(SourceRange R) { - assert(Name.getNameKind() == DeclarationName::CXXOperatorName); - LocInfo = DeclarationNameLoc::makeCXXOperatorNameLoc(R); - } - /// getCXXLiteralOperatorNameLoc - Returns the location of the literal /// operator name (not the operator keyword). /// Assumes it is a literal operator. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index d95396fd59b95..483522547ea77 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1182,7 +1182,7 @@ class OpaqueValueExpr : public Expr { ExprObjectKind OK = OK_Ordinary, Expr *SourceExpr = nullptr) : Expr(OpaqueValueExprClass, T, VK, OK), SourceExpr(SourceExpr) { setIsUnique(false); - OpaqueValueExprBits.Loc = Loc; + OpaqueValueExprBits.Loc = Loc.getRawEncoding(); setDependence(computeDependence(this)); } @@ -1195,7 +1195,9 @@ class OpaqueValueExpr : public Expr { : Expr(OpaqueValueExprClass, Empty) {} /// Retrieve the location of this expression. - SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; } + SourceLocation getLocation() const { + return SourceLocation::getFromRawEncoding(OpaqueValueExprBits.Loc); + } SourceLocation getBeginLoc() const LLVM_READONLY { return SourceExpr ? SourceExpr->getBeginLoc() : getLocation(); @@ -1270,6 +1272,9 @@ class DeclRefExpr final friend class ASTStmtWriter; friend TrailingObjects; + /// The location of the declaration name itself. + SourceLocation Loc; + /// The declaration that we are referencing. ValueDecl *D; @@ -1341,13 +1346,13 @@ class DeclRefExpr final return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc); } - SourceLocation getLocation() const { return DeclRefExprBits.Loc; } - void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } SourceLocation getBeginLoc() const { if (hasQualifier()) return getQualifierLoc().getBeginLoc(); - return DeclRefExprBits.Loc; + return Loc; } SourceLocation getEndLoc() const LLVM_READONLY; @@ -2004,6 +2009,9 @@ class PredefinedExpr final friend class ASTStmtReader; friend TrailingObjects; + /// The location of this PredefinedExpr. + SourceLocation Loc; + // PredefinedExpr is optionally followed by a single trailing // "Stmt *" for the predefined identifier. It is present if and only if // hasFunctionName() is true and is always a "StringLiteral *". @@ -2041,8 +2049,8 @@ class PredefinedExpr final bool isTransparent() const { return PredefinedExprBits.IsTransparent; } - SourceLocation getLocation() const { return PredefinedExprBits.Loc; } - void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } StringLiteral *getFunctionName() { return hasFunctionName() @@ -2240,6 +2248,7 @@ class ParenExpr : public Expr { class UnaryOperator final : public Expr, private llvm::TrailingObjects { + SourceLocation Loc; Stmt *Val; FPOptionsOverride &getTrailingFPFeatures() { @@ -2284,8 +2293,8 @@ class UnaryOperator final void setSubExpr(Expr *E) { Val = E; } /// getOperatorLoc - Return the location of the operator. - SourceLocation getOperatorLoc() const { return UnaryOperatorBits.Loc; } - void setOperatorLoc(SourceLocation L) { UnaryOperatorBits.Loc = L; } + SourceLocation getOperatorLoc() const { return Loc; } + void setOperatorLoc(SourceLocation L) { Loc = L; } /// Returns true if the unary operator can cause an overflow. For instance, /// signed int i = INT_MAX; i++; @@ -2728,7 +2737,7 @@ class ArraySubscriptExpr : public Expr { : Expr(ArraySubscriptExprClass, t, VK, OK) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - ArrayOrMatrixSubscriptExprBits.RBracketLoc = rbracketloc; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = rbracketloc.getRawEncoding(); setDependence(computeDependence(this)); } @@ -2765,10 +2774,11 @@ class ArraySubscriptExpr : public Expr { SourceLocation getEndLoc() const { return getRBracketLoc(); } SourceLocation getRBracketLoc() const { - return ArrayOrMatrixSubscriptExprBits.RBracketLoc; + return SourceLocation::getFromRawEncoding( + ArrayOrMatrixSubscriptExprBits.RBracketLoc); } void setRBracketLoc(SourceLocation L) { - ArrayOrMatrixSubscriptExprBits.RBracketLoc = L; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = L.getRawEncoding(); } SourceLocation getExprLoc() const LLVM_READONLY { @@ -2806,7 +2816,7 @@ class MatrixSubscriptExpr : public Expr { SubExprs[BASE] = Base; SubExprs[ROW_IDX] = RowIdx; SubExprs[COLUMN_IDX] = ColumnIdx; - ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc.getRawEncoding(); setDependence(computeDependence(this)); } @@ -2847,10 +2857,11 @@ class MatrixSubscriptExpr : public Expr { } SourceLocation getRBracketLoc() const { - return ArrayOrMatrixSubscriptExprBits.RBracketLoc; + return SourceLocation::getFromRawEncoding( + ArrayOrMatrixSubscriptExprBits.RBracketLoc); } void setRBracketLoc(SourceLocation L) { - ArrayOrMatrixSubscriptExprBits.RBracketLoc = L; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = L.getRawEncoding(); } static bool classof(const Stmt *T) { @@ -2875,9 +2886,6 @@ class MatrixSubscriptExpr : public Expr { class CallExpr : public Expr { enum { FN = 0, PREARGS_START = 1 }; - /// The number of arguments in the call expression. - unsigned NumArgs; - /// The location of the right parentheses. This has a different meaning for /// the derived classes of CallExpr. SourceLocation RParenLoc; @@ -2904,7 +2912,7 @@ class CallExpr : public Expr { // the begin source location, which has a significant impact on perf as // getBeginLoc is assumed to be cheap. // The layourt is as follow: - // CallExpr | Begin | 4 bytes left | Trailing Objects + // CallExpr | Begin | Trailing Objects // CXXMemberCallExpr | Trailing Objects // A bit in CallExprBitfields indicates if source locations are present. @@ -3063,7 +3071,7 @@ class CallExpr : public Expr { } /// getNumArgs - Return the number of actual arguments to this call. - unsigned getNumArgs() const { return NumArgs; } + unsigned getNumArgs() const { return CallExprBits.NumArgs; } /// Retrieve the call arguments. Expr **getArgs() { @@ -3111,13 +3119,15 @@ class CallExpr : public Expr { void shrinkNumArgs(unsigned NewNumArgs) { assert((NewNumArgs <= getNumArgs()) && "shrinkNumArgs cannot increase the number of arguments!"); - NumArgs = NewNumArgs; + CallExprBits.NumArgs = NewNumArgs; } /// Bluntly set a new number of arguments without doing any checks whatsoever. /// Only used during construction of a CallExpr in a few places in Sema. /// FIXME: Find a way to remove it. - void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; } + void setNumArgsUnsafe(unsigned NewNumArgs) { + CallExprBits.NumArgs = NewNumArgs; + } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -3303,6 +3313,8 @@ class MemberExpr final /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; + SourceLocation OperatorLoc; + size_t numTrailingObjects(OverloadToken) const { return hasQualifier(); } @@ -3464,7 +3476,7 @@ class MemberExpr final MemberLoc, MemberDNLoc); } - SourceLocation getOperatorLoc() const { return MemberExprBits.OperatorLoc; } + SourceLocation getOperatorLoc() const { return OperatorLoc; } bool isArrow() const { return MemberExprBits.IsArrow; } void setArrow(bool A) { MemberExprBits.IsArrow = A; } @@ -3958,6 +3970,7 @@ class CStyleCastExpr final class BinaryOperator : public Expr { enum { LHS, RHS, END_EXPR }; Stmt *SubExprs[END_EXPR]; + SourceLocation OpLoc; public: typedef BinaryOperatorKind Opcode; @@ -3997,8 +4010,8 @@ class BinaryOperator : public Expr { ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures); SourceLocation getExprLoc() const { return getOperatorLoc(); } - SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; } - void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; } + SourceLocation getOperatorLoc() const { return OpLoc; } + void setOperatorLoc(SourceLocation L) { OpLoc = L; } Opcode getOpcode() const { return static_cast(BinaryOperatorBits.Opc); @@ -6449,7 +6462,8 @@ class GenericSelectionExpr final } SourceLocation getGenericLoc() const { - return GenericSelectionExprBits.GenericLoc; + return SourceLocation::getFromRawEncoding( + GenericSelectionExprBits.GenericLoc); } SourceLocation getDefaultLoc() const { return DefaultLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index a22c32241ac61..1eac5f80608f3 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -724,7 +724,7 @@ class CXXBoolLiteralExpr : public Expr { CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc) : Expr(CXXBoolLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { CXXBoolLiteralExprBits.Value = Val; - CXXBoolLiteralExprBits.Loc = Loc; + CXXBoolLiteralExprBits.Loc = Loc.getRawEncoding(); setDependence(ExprDependence::None); } @@ -742,8 +742,12 @@ class CXXBoolLiteralExpr : public Expr { SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } - SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; } - void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; } + SourceLocation getLocation() const { + return SourceLocation::getFromRawEncoding(CXXBoolLiteralExprBits.Loc); + } + void setLocation(SourceLocation L) { + CXXBoolLiteralExprBits.Loc = L.getRawEncoding(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBoolLiteralExprClass; @@ -768,7 +772,7 @@ class CXXNullPtrLiteralExpr : public Expr { public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) : Expr(CXXNullPtrLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { - CXXNullPtrLiteralExprBits.Loc = Loc; + CXXNullPtrLiteralExprBits.Loc = Loc.getRawEncoding(); setDependence(ExprDependence::None); } @@ -778,8 +782,12 @@ class CXXNullPtrLiteralExpr : public Expr { SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } - SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; } - void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; } + SourceLocation getLocation() const { + return SourceLocation::getFromRawEncoding(CXXNullPtrLiteralExprBits.Loc); + } + void setLocation(SourceLocation L) { + CXXNullPtrLiteralExprBits.Loc = L.getRawEncoding(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNullPtrLiteralExprClass; @@ -1156,7 +1164,7 @@ class CXXThisExpr : public Expr { : Expr(CXXThisExprClass, Ty, VK, OK_Ordinary) { CXXThisExprBits.IsImplicit = IsImplicit; CXXThisExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; - CXXThisExprBits.Loc = L; + CXXThisExprBits.Loc = L.getRawEncoding(); setDependence(computeDependence(this)); } @@ -1168,8 +1176,12 @@ class CXXThisExpr : public Expr { static CXXThisExpr *CreateEmpty(const ASTContext &Ctx); - SourceLocation getLocation() const { return CXXThisExprBits.Loc; } - void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } + SourceLocation getLocation() const { + return SourceLocation::getFromRawEncoding(CXXThisExprBits.Loc); + } + void setLocation(SourceLocation L) { + CXXThisExprBits.Loc = L.getRawEncoding(); + } SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } @@ -1219,7 +1231,7 @@ class CXXThrowExpr : public Expr { CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc, bool IsThrownVariableInScope) : Expr(CXXThrowExprClass, Ty, VK_PRValue, OK_Ordinary), Operand(Operand) { - CXXThrowExprBits.ThrowLoc = Loc; + CXXThrowExprBits.ThrowLoc = Loc.getRawEncoding(); CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope; setDependence(computeDependence(this)); } @@ -1228,7 +1240,9 @@ class CXXThrowExpr : public Expr { const Expr *getSubExpr() const { return cast_or_null(Operand); } Expr *getSubExpr() { return cast_or_null(Operand); } - SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; } + SourceLocation getThrowLoc() const { + return SourceLocation::getFromRawEncoding(CXXThrowExprBits.ThrowLoc); + } /// Determines whether the variable thrown by this expression (if any!) /// is within the innermost try block. @@ -1287,7 +1301,7 @@ class CXXDefaultArgExpr final Param->getDefaultArg()->getValueKind(), Param->getDefaultArg()->getObjectKind()), Param(Param), UsedContext(UsedContext) { - CXXDefaultArgExprBits.Loc = Loc; + CXXDefaultArgExprBits.Loc = Loc.getRawEncoding(); CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr; if (RewrittenExpr) *getTrailingObjects() = RewrittenExpr; @@ -1341,7 +1355,9 @@ class CXXDefaultArgExpr final DeclContext *getUsedContext() { return UsedContext; } /// Retrieve the location where this default argument was actually used. - SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; } + SourceLocation getUsedLocation() const { + return SourceLocation::getFromRawEncoding(CXXDefaultArgExprBits.Loc); + } /// Default argument expressions have no representation in the /// source, so they have an empty source range. @@ -1384,7 +1400,6 @@ class CXXDefaultInitExpr final /// The context where the default initializer expression was used. DeclContext *UsedContext; - CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, FieldDecl *Field, QualType Ty, DeclContext *UsedContext, Expr *RewrittenInitExpr); @@ -1438,8 +1453,10 @@ class CXXDefaultInitExpr final /// actually used. SourceLocation getUsedLocation() const { return getBeginLoc(); } - SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; } - SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; } + SourceLocation getBeginLoc() const { + return SourceLocation::getFromRawEncoding(CXXDefaultInitExprBits.Loc); + } + SourceLocation getEndLoc() const { return getBeginLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDefaultInitExprClass; @@ -1556,6 +1573,7 @@ class CXXConstructExpr : public Expr { /// The number of arguments. unsigned NumArgs; + SourceLocation Loc; // We would like to stash the arguments of the constructor call after // CXXConstructExpr. However CXXConstructExpr is used as a base class of // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects @@ -1610,8 +1628,8 @@ class CXXConstructExpr : public Expr { /// Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } - SourceLocation getLocation() const { return CXXConstructExprBits.Loc; } - void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation Loc) { this->Loc = Loc; } /// Whether this construction is elidable. bool isElidable() const { return CXXConstructExprBits.Elidable; } @@ -2193,7 +2211,7 @@ class CXXScalarValueInitExpr : public Expr { SourceLocation RParenLoc) : Expr(CXXScalarValueInitExprClass, Type, VK_PRValue, OK_Ordinary), TypeInfo(TypeInfo) { - CXXScalarValueInitExprBits.RParenLoc = RParenLoc; + CXXScalarValueInitExprBits.RParenLoc = RParenLoc.getRawEncoding(); setDependence(computeDependence(this)); } @@ -2205,7 +2223,8 @@ class CXXScalarValueInitExpr : public Expr { } SourceLocation getRParenLoc() const { - return CXXScalarValueInitExprBits.RParenLoc; + return SourceLocation::getFromRawEncoding( + CXXScalarValueInitExprBits.RParenLoc); } SourceLocation getBeginLoc() const LLVM_READONLY; @@ -2622,7 +2641,7 @@ class CXXDeleteExpr : public Expr { CXXDeleteExprBits.ArrayForm = ArrayForm; CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten; CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; - CXXDeleteExprBits.Loc = Loc; + CXXDeleteExprBits.Loc = Loc.getRawEncoding(); setDependence(computeDependence(this)); } @@ -2653,7 +2672,9 @@ class CXXDeleteExpr : public Expr { /// be a pointer, return an invalid type. QualType getDestroyedType() const; - SourceLocation getBeginLoc() const { return CXXDeleteExprBits.Loc; } + SourceLocation getBeginLoc() const { + return SourceLocation::getFromRawEncoding(CXXDeleteExprBits.Loc); + } SourceLocation getEndLoc() const LLVM_READONLY { return Argument->getEndLoc(); } @@ -3908,7 +3929,8 @@ class CXXDependentScopeMemberExpr final /// Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { - return CXXDependentScopeMemberExprBits.OperatorLoc; + return SourceLocation::getFromRawEncoding( + CXXDependentScopeMemberExprBits.OperatorLoc); } /// Retrieve the nested-name-specifier that qualifies the member name. @@ -4630,12 +4652,13 @@ class SubstNonTypeTemplateParmExpr : public Expr { AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index), PackIndex(PackIndex.toInternalRepresentation()), Final(Final) { assert(AssociatedDecl != nullptr); - SubstNonTypeTemplateParmExprBits.NameLoc = Loc; + SubstNonTypeTemplateParmExprBits.NameLoc = Loc.getRawEncoding(); setDependence(computeDependence(this)); } SourceLocation getNameLoc() const { - return SubstNonTypeTemplateParmExprBits.NameLoc; + return SourceLocation::getFromRawEncoding( + SubstNonTypeTemplateParmExprBits.NameLoc); } SourceLocation getBeginLoc() const { return getNameLoc(); } SourceLocation getEndLoc() const { return getNameLoc(); } diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h index 8df5cdcaa9d75..c6724315194f9 100644 --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -502,6 +502,7 @@ class RequiresExpr final : public Expr, concepts::Requirement *> { friend TrailingObjects; friend class ASTStmtReader; + friend class ASTStmtWriter; unsigned NumLocalParameters; unsigned NumRequirements; @@ -560,7 +561,7 @@ class RequiresExpr final : public Expr, } SourceLocation getRequiresKWLoc() const { - return RequiresExprBits.RequiresKWLoc; + return SourceLocation::getFromRawEncoding(RequiresExprBits.RequiresKWLoc); } SourceLocation getLParenLoc() const { return LParenLoc; } @@ -572,7 +573,7 @@ class RequiresExpr final : public Expr, } SourceLocation getBeginLoc() const LLVM_READONLY { - return RequiresExprBits.RequiresKWLoc; + return getRequiresKWLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { return RBraceLoc; diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index e91d5132da10f..01dd56b576200 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -110,7 +110,7 @@ class ExternalASTSource : public RefCountedBase { /// returns non-zero for GetNumKnownSelectors(). /// /// The default implementation of this method is a no-op. - virtual Selector GetExternalSelector(uint32_t ID); + virtual Selector GetExternalSelector(uint64_t ID); /// Returns the number of selectors known to the external AST /// source. diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index a5b0d5053003f..5cbca8714dffb 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -128,7 +128,7 @@ class alignas(void *) Stmt { friend class NullStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// True if the null statement was preceded by an empty macro, e.g: /// @code @@ -136,10 +136,11 @@ class alignas(void *) Stmt { /// CALL(0); /// @endcode LLVM_PREFERRED_TYPE(bool) - unsigned HasLeadingEmptyMacro : 1; + uint64_t HasLeadingEmptyMacro : 1; - /// The location of the semi-colon. - SourceLocation SemiLoc; + /// The location of the semi-colon.Add commentMore actions + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t SemiLoc : SourceLocation::Bits; }; class CompoundStmtBitfields { @@ -161,9 +162,10 @@ class alignas(void *) Stmt { friend class LabelStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; - SourceLocation IdentLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t IdentLoc : SourceLocation::Bits; }; class AttributedStmtBitfields { @@ -175,9 +177,6 @@ class alignas(void *) Stmt { /// Number of attributes. unsigned NumAttrs : 32 - NumStmtBits; - - /// The location of the attribute. - SourceLocation AttrLoc; }; class IfStmtBitfields { @@ -185,50 +184,52 @@ class alignas(void *) Stmt { friend class IfStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// Whether this is a constexpr if, or a consteval if, or neither. LLVM_PREFERRED_TYPE(IfStatementKind) - unsigned Kind : 3; + uint64_t Kind : 3; /// True if this if statement has storage for an else statement. LLVM_PREFERRED_TYPE(bool) - unsigned HasElse : 1; + uint64_t HasElse : 1; /// True if this if statement has storage for a variable declaration. LLVM_PREFERRED_TYPE(bool) - unsigned HasVar : 1; + uint64_t HasVar : 1; /// True if this if statement has storage for an init statement. LLVM_PREFERRED_TYPE(bool) - unsigned HasInit : 1; + uint64_t HasInit : 1; /// The location of the "if". - SourceLocation IfLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t IfLoc : SourceLocation::Bits; }; class SwitchStmtBitfields { friend class SwitchStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// True if the SwitchStmt has storage for an init statement. LLVM_PREFERRED_TYPE(bool) - unsigned HasInit : 1; + uint64_t HasInit : 1; /// True if the SwitchStmt has storage for a condition variable. LLVM_PREFERRED_TYPE(bool) - unsigned HasVar : 1; + uint64_t HasVar : 1; /// If the SwitchStmt is a switch on an enum value, records whether all /// the enum values were covered by CaseStmts. The coverage information /// value is meant to be a hint for possible clients. LLVM_PREFERRED_TYPE(bool) - unsigned AllEnumCasesCovered : 1; + uint64_t AllEnumCasesCovered : 1; /// The location of the "switch". - SourceLocation SwitchLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t SwitchLoc : SourceLocation::Bits; }; class WhileStmtBitfields { @@ -236,34 +237,37 @@ class alignas(void *) Stmt { friend class WhileStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// True if the WhileStmt has storage for a condition variable. LLVM_PREFERRED_TYPE(bool) - unsigned HasVar : 1; + uint64_t HasVar : 1; /// The location of the "while". - SourceLocation WhileLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t WhileLoc : SourceLocation::Bits; }; class DoStmtBitfields { friend class DoStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; - /// The location of the "do". - SourceLocation DoLoc; + /// The location of the "do" + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t DoLoc : SourceLocation::Bits; }; class ForStmtBitfields { friend class ForStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// The location of the "for". - SourceLocation ForLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t ForLoc : SourceLocation::Bits; }; class GotoStmtBitfields { @@ -271,44 +275,48 @@ class alignas(void *) Stmt { friend class IndirectGotoStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// The location of the "goto". - SourceLocation GotoLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t GotoLoc : SourceLocation::Bits; }; class ContinueStmtBitfields { friend class ContinueStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// The location of the "continue". - SourceLocation ContinueLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t ContinueLoc : SourceLocation::Bits; }; class BreakStmtBitfields { friend class BreakStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// The location of the "break". - SourceLocation BreakLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t BreakLoc : SourceLocation::Bits; }; class ReturnStmtBitfields { friend class ReturnStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// True if this ReturnStmt has storage for an NRVO candidate. LLVM_PREFERRED_TYPE(bool) - unsigned HasNRVOCandidate : 1; + uint64_t HasNRVOCandidate : 1; /// The location of the "return". - SourceLocation RetLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t RetLoc : SourceLocation::Bits; }; class SwitchCaseBitfields { @@ -316,15 +324,16 @@ class alignas(void *) Stmt { friend class CaseStmt; LLVM_PREFERRED_TYPE(StmtBitfields) - unsigned : NumStmtBits; + uint64_t : NumStmtBits; /// Used by CaseStmt to store whether it is a case statement /// of the form case LHS ... RHS (a GNU extension). LLVM_PREFERRED_TYPE(bool) - unsigned CaseStmtIsGNURange : 1; + uint64_t CaseStmtIsGNURange : 1; /// The location of the "case" or "default" keyword. - SourceLocation KeywordLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t KeywordLoc : SourceLocation::Bits; }; //===--- Expression bitfields classes ---===// @@ -421,9 +430,6 @@ class alignas(void *) Stmt { /// MSVC compatibility). LLVM_PREFERRED_TYPE(bool) unsigned IsTransparent : 1; - - /// The location of this PredefinedExpr. - SourceLocation Loc; }; class DeclRefExprBitfields { @@ -449,9 +455,6 @@ class alignas(void *) Stmt { unsigned NonOdrUseReason : 2; LLVM_PREFERRED_TYPE(bool) unsigned IsImmediateEscalating : 1; - - /// The location of the declaration name itself. - SourceLocation Loc; }; @@ -521,8 +524,6 @@ class alignas(void *) Stmt { /// It is 0 otherwise. LLVM_PREFERRED_TYPE(bool) unsigned HasFPFeatures : 1; - - SourceLocation Loc; }; class UnaryExprOrTypeTraitExprBitfields { @@ -542,9 +543,10 @@ class alignas(void *) Stmt { friend class MatrixSubscriptExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; - SourceLocation RBracketLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t RBracketLoc : SourceLocation::Bits; }; class CallExprBitfields { @@ -576,9 +578,10 @@ class alignas(void *) Stmt { /// Trailing objects. See the definition of CallExpr. LLVM_PREFERRED_TYPE(bool) unsigned HasTrailingSourceLoc : 1; - }; - enum { NumCallExprBits = 25 }; + unsigned NumArgs : 20; + }; + enum { NumCallExprBits = 52 }; class MemberExprBitfields { friend class ASTStmtReader; @@ -618,9 +621,6 @@ class alignas(void *) Stmt { /// when naming a static member. LLVM_PREFERRED_TYPE(NonOdrUseReason) unsigned NonOdrUseReason : 2; - - /// This is the location of the -> or . in the expression. - SourceLocation OperatorLoc; }; class CastExprBitfields { @@ -663,8 +663,6 @@ class alignas(void *) Stmt { /// overflow sanitization. LLVM_PREFERRED_TYPE(bool) unsigned ExcludedOverflowPattern : 1; - - SourceLocation OpLoc; }; class InitListExprBitfields { @@ -695,10 +693,11 @@ class alignas(void *) Stmt { friend class GenericSelectionExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// The location of the "_Generic". - SourceLocation GenericLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t GenericLoc : SourceLocation::Bits; }; class PseudoObjectExprBitfields { @@ -777,12 +776,12 @@ class alignas(void *) Stmt { friend class CXXOperatorCallExpr; LLVM_PREFERRED_TYPE(CallExprBitfields) - unsigned : NumCallExprBits; + uint64_t : NumCallExprBits; /// The kind of this overloaded operator. One of the enumerator /// value of OverloadedOperatorKind. LLVM_PREFERRED_TYPE(OverloadedOperatorKind) - unsigned OperatorKind : 6; + uint64_t OperatorKind : 6; }; class CXXRewrittenBinaryOperatorBitfields { @@ -790,53 +789,56 @@ class alignas(void *) Stmt { friend class CXXRewrittenBinaryOperator; LLVM_PREFERRED_TYPE(CallExprBitfields) - unsigned : NumCallExprBits; + uint64_t : NumCallExprBits; LLVM_PREFERRED_TYPE(bool) - unsigned IsReversed : 1; + uint64_t IsReversed : 1; }; class CXXBoolLiteralExprBitfields { friend class CXXBoolLiteralExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// The value of the boolean literal. LLVM_PREFERRED_TYPE(bool) - unsigned Value : 1; + uint64_t Value : 1; - /// The location of the boolean literal. - SourceLocation Loc; + /// The location of the boolean ligeral. + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class CXXNullPtrLiteralExprBitfields { friend class CXXNullPtrLiteralExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// The location of the null pointer literal. - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class CXXThisExprBitfields { friend class CXXThisExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Whether this is an implicit "this". LLVM_PREFERRED_TYPE(bool) - unsigned IsImplicit : 1; + uint64_t IsImplicit : 1; /// Whether there is a lambda with an explicit object parameter that /// captures this "this" by copy. LLVM_PREFERRED_TYPE(bool) - unsigned CapturedByCopyInLambdaWithExplicitObjectParameter : 1; + uint64_t CapturedByCopyInLambdaWithExplicitObjectParameter : 1; /// The location of the "this". - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class CXXThrowExprBitfields { @@ -844,14 +846,15 @@ class alignas(void *) Stmt { friend class CXXThrowExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Whether the thrown variable (if any) is in scope. LLVM_PREFERRED_TYPE(bool) - unsigned IsThrownVariableInScope : 1; + uint64_t IsThrownVariableInScope : 1; /// The location of the "throw". - SourceLocation ThrowLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t ThrowLoc : SourceLocation::Bits; }; class CXXDefaultArgExprBitfields { @@ -859,14 +862,15 @@ class alignas(void *) Stmt { friend class CXXDefaultArgExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Whether this CXXDefaultArgExpr rewrote its argument and stores a copy. LLVM_PREFERRED_TYPE(bool) - unsigned HasRewrittenInit : 1; + uint64_t HasRewrittenInit : 1; /// The location where the default argument expression was used. - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class CXXDefaultInitExprBitfields { @@ -874,15 +878,16 @@ class alignas(void *) Stmt { friend class CXXDefaultInitExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Whether this CXXDefaultInitExprBitfields rewrote its argument and stores /// a copy. LLVM_PREFERRED_TYPE(bool) - unsigned HasRewrittenInit : 1; + uint64_t HasRewrittenInit : 1; /// The location where the default initializer expression was used. - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class CXXScalarValueInitExprBitfields { @@ -890,9 +895,10 @@ class alignas(void *) Stmt { friend class CXXScalarValueInitExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; - SourceLocation RParenLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t RParenLoc : SourceLocation::Bits; }; class CXXNewExprBitfields { @@ -946,29 +952,30 @@ class alignas(void *) Stmt { friend class CXXDeleteExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Is this a forced global delete, i.e. "::delete"? LLVM_PREFERRED_TYPE(bool) - unsigned GlobalDelete : 1; + uint64_t GlobalDelete : 1; /// Is this the array form of delete, i.e. "delete[]"? LLVM_PREFERRED_TYPE(bool) - unsigned ArrayForm : 1; + uint64_t ArrayForm : 1; /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is /// applied to pointer-to-array type (ArrayFormAsWritten will be false /// while ArrayForm will be true). LLVM_PREFERRED_TYPE(bool) - unsigned ArrayFormAsWritten : 1; + uint64_t ArrayFormAsWritten : 1; /// Does the usual deallocation function for the element type require /// a size_t argument? LLVM_PREFERRED_TYPE(bool) - unsigned UsualArrayDeleteWantsSize : 1; + uint64_t UsualArrayDeleteWantsSize : 1; /// Location of the expression. - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class TypeTraitExprBitfields { @@ -1031,8 +1038,6 @@ class alignas(void *) Stmt { unsigned ConstructionKind : 3; LLVM_PREFERRED_TYPE(bool) unsigned IsImmediateEscalating : 1; - - SourceLocation Loc; }; class ExprWithCleanupsBitfields { @@ -1065,25 +1070,26 @@ class alignas(void *) Stmt { friend class CXXDependentScopeMemberExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// Whether this member expression used the '->' operator or /// the '.' operator. LLVM_PREFERRED_TYPE(bool) - unsigned IsArrow : 1; + uint64_t IsArrow : 1; /// Whether this member expression has info for explicit template /// keyword and arguments. LLVM_PREFERRED_TYPE(bool) - unsigned HasTemplateKWAndArgsInfo : 1; + uint64_t HasTemplateKWAndArgsInfo : 1; /// See getFirstQualifierFoundInScope() and the comment listing /// the trailing objects. LLVM_PREFERRED_TYPE(bool) - unsigned HasFirstQualifierFoundInScope : 1; + uint64_t HasFirstQualifierFoundInScope : 1; /// The location of the '->' or '.' operator. - SourceLocation OperatorLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t OperatorLoc : SourceLocation::Bits; }; class OverloadExprBitfields { @@ -1160,10 +1166,11 @@ class alignas(void *) Stmt { friend class SubstNonTypeTemplateParmExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// The location of the non-type template parameter reference. - SourceLocation NameLoc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t NameLoc : SourceLocation::Bits; }; class LambdaExprBitfields { @@ -1198,11 +1205,13 @@ class alignas(void *) Stmt { friend class RequiresExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; LLVM_PREFERRED_TYPE(bool) - unsigned IsSatisfied : 1; - SourceLocation RequiresKWLoc; + uint64_t IsSatisfied : 1; + + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t RequiresKWLoc : SourceLocation::Bits; }; class ArrayTypeTraitExprBitfields { @@ -1287,14 +1296,15 @@ class alignas(void *) Stmt { friend class OpaqueValueExpr; LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; + uint64_t : NumExprBits; /// The OVE is a unique semantic reference to its source expression if this /// bit is set to true. LLVM_PREFERRED_TYPE(bool) - unsigned IsUnique : 1; + uint64_t IsUnique : 1; - SourceLocation Loc; + LLVM_PREFERRED_TYPE(SourceLocation) + uint64_t Loc : SourceLocation::Bits; }; class ConvertVectorExprBitfields { @@ -1702,8 +1712,12 @@ class NullStmt : public Stmt { /// Build an empty null statement. explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {} - SourceLocation getSemiLoc() const { return NullStmtBits.SemiLoc; } - void setSemiLoc(SourceLocation L) { NullStmtBits.SemiLoc = L; } + SourceLocation getSemiLoc() const { + return SourceLocation::getFromRawEncoding(NullStmtBits.SemiLoc); + } + void setSemiLoc(SourceLocation L) { + NullStmtBits.SemiLoc = L.getRawEncoding(); + } bool hasLeadingEmptyMacro() const { return NullStmtBits.HasLeadingEmptyMacro; @@ -1905,8 +1919,12 @@ class SwitchCase : public Stmt { SwitchCase *getNextSwitchCase() { return NextSwitchCase; } void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } - SourceLocation getKeywordLoc() const { return SwitchCaseBits.KeywordLoc; } - void setKeywordLoc(SourceLocation L) { SwitchCaseBits.KeywordLoc = L; } + SourceLocation getKeywordLoc() const { + return SourceLocation::getFromRawEncoding(SwitchCaseBits.KeywordLoc); + } + void setKeywordLoc(SourceLocation L) { + SwitchCaseBits.KeywordLoc = L.getRawEncoding(); + } SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } @@ -1948,7 +1966,8 @@ class CaseStmt final // with a range. Present if and only if caseStmtIsGNURange() is true. enum { LhsOffset = 0, SubStmtOffsetFromRhs = 1 }; enum { NumMandatoryStmtPtr = 2 }; - + /// The location of the "case" or "default" keyword. + SourceLocation KeywordLoc; unsigned numTrailingObjects(OverloadToken) const { return NumMandatoryStmtPtr + caseStmtIsGNURange(); } @@ -2169,8 +2188,12 @@ class LabelStmt : public ValueStmt { /// Build an empty label statement. explicit LabelStmt(EmptyShell Empty) : ValueStmt(LabelStmtClass, Empty) {} - SourceLocation getIdentLoc() const { return LabelStmtBits.IdentLoc; } - void setIdentLoc(SourceLocation L) { LabelStmtBits.IdentLoc = L; } + SourceLocation getIdentLoc() const { + return SourceLocation::getFromRawEncoding(LabelStmtBits.IdentLoc); + } + void setIdentLoc(SourceLocation L) { + LabelStmtBits.IdentLoc = L.getRawEncoding(); + } LabelDecl *getDecl() const { return TheDecl; } void setDecl(LabelDecl *D) { TheDecl = D; } @@ -2206,21 +2229,22 @@ class AttributedStmt final private llvm::TrailingObjects { friend class ASTStmtReader; friend TrailingObjects; - + /// The location of the attribute. + SourceLocation AttrLoc; Stmt *SubStmt; AttributedStmt(SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt) : ValueStmt(AttributedStmtClass), SubStmt(SubStmt) { AttributedStmtBits.NumAttrs = Attrs.size(); - AttributedStmtBits.AttrLoc = Loc; + AttrLoc = Loc; llvm::copy(Attrs, getAttrArrayPtr()); } explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) : ValueStmt(AttributedStmtClass, Empty) { AttributedStmtBits.NumAttrs = NumAttrs; - AttributedStmtBits.AttrLoc = SourceLocation{}; + AttrLoc = SourceLocation{}; std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr); } @@ -2234,7 +2258,7 @@ class AttributedStmt final // Build an empty attributed statement. static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); - SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; } + SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef getAttrs() const { return {getAttrArrayPtr(), AttributedStmtBits.NumAttrs}; } @@ -2425,8 +2449,12 @@ class IfStmt final getTrailingObjects()[initOffset()] = Init; } - SourceLocation getIfLoc() const { return IfStmtBits.IfLoc; } - void setIfLoc(SourceLocation IfLoc) { IfStmtBits.IfLoc = IfLoc; } + SourceLocation getIfLoc() const { + return SourceLocation::getFromRawEncoding(IfStmtBits.IfLoc); + } + void setIfLoc(SourceLocation IfLoc) { + IfStmtBits.IfLoc = IfLoc.getRawEncoding(); + } SourceLocation getElseLoc() const { return hasElseStorage() ? *getTrailingObjects() @@ -2515,6 +2543,9 @@ class SwitchStmt final : public Stmt, /// Points to a linked list of case and default statements. SwitchCase *FirstCase = nullptr; + SourceLocation LParenLoc; + SourceLocation RParenLoc; + // SwitchStmt is followed by several trailing objects, // some of which optional. Note that it would be more convenient to // put the optional trailing objects at the end but this would change @@ -2534,8 +2565,6 @@ class SwitchStmt final : public Stmt, // Always present. enum { InitOffset = 0, BodyOffsetFromCond = 1 }; enum { NumMandatoryStmtPtr = 2 }; - SourceLocation LParenLoc; - SourceLocation RParenLoc; unsigned numTrailingStatements() const { return NumMandatoryStmtPtr + hasInitStorage() + hasVarStorage(); @@ -2644,8 +2673,12 @@ class SwitchStmt final : public Stmt, const SwitchCase *getSwitchCaseList() const { return FirstCase; } void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } - SourceLocation getSwitchLoc() const { return SwitchStmtBits.SwitchLoc; } - void setSwitchLoc(SourceLocation L) { SwitchStmtBits.SwitchLoc = L; } + SourceLocation getSwitchLoc() const { + return SourceLocation::getFromRawEncoding(SwitchStmtBits.SwitchLoc); + } + void setSwitchLoc(SourceLocation L) { + SwitchStmtBits.SwitchLoc = L.getRawEncoding(); + } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -2802,8 +2835,12 @@ class WhileStmt final : public Stmt, getTrailingObjects()[varOffset()] = CondVar; } - SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; } - void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; } + SourceLocation getWhileLoc() const { + return SourceLocation::getFromRawEncoding(WhileStmtBits.WhileLoc); + } + void setWhileLoc(SourceLocation L) { + WhileStmtBits.WhileLoc = L.getRawEncoding(); + } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } @@ -2861,8 +2898,10 @@ class DoStmt : public Stmt { const Stmt *getBody() const { return SubExprs[BODY]; } void setBody(Stmt *Body) { SubExprs[BODY] = Body; } - SourceLocation getDoLoc() const { return DoStmtBits.DoLoc; } - void setDoLoc(SourceLocation L) { DoStmtBits.DoLoc = L; } + SourceLocation getDoLoc() const { + return SourceLocation::getFromRawEncoding(DoStmtBits.DoLoc); + } + void setDoLoc(SourceLocation L) { DoStmtBits.DoLoc = L.getRawEncoding(); } SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -2944,8 +2983,10 @@ class ForStmt : public Stmt { void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast(E); } void setBody(Stmt *S) { SubExprs[BODY] = S; } - SourceLocation getForLoc() const { return ForStmtBits.ForLoc; } - void setForLoc(SourceLocation L) { ForStmtBits.ForLoc = L; } + SourceLocation getForLoc() const { + return SourceLocation::getFromRawEncoding(ForStmtBits.ForLoc); + } + void setForLoc(SourceLocation L) { ForStmtBits.ForLoc = L.getRawEncoding(); } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -2985,8 +3026,12 @@ class GotoStmt : public Stmt { LabelDecl *getLabel() const { return Label; } void setLabel(LabelDecl *D) { Label = D; } - SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; } - void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; } + SourceLocation getGotoLoc() const { + return SourceLocation::getFromRawEncoding(GotoStmtBits.GotoLoc); + } + void setGotoLoc(SourceLocation L) { + GotoStmtBits.GotoLoc = L.getRawEncoding(); + } SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } @@ -3023,8 +3068,12 @@ class IndirectGotoStmt : public Stmt { explicit IndirectGotoStmt(EmptyShell Empty) : Stmt(IndirectGotoStmtClass, Empty) {} - void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; } - SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; } + void setGotoLoc(SourceLocation L) { + GotoStmtBits.GotoLoc = L.getRawEncoding(); + } + SourceLocation getGotoLoc() const { + return SourceLocation::getFromRawEncoding(GotoStmtBits.GotoLoc); + } void setStarLoc(SourceLocation L) { StarLoc = L; } SourceLocation getStarLoc() const { return StarLoc; } @@ -3066,8 +3115,12 @@ class ContinueStmt : public Stmt { /// Build an empty continue statement. explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {} - SourceLocation getContinueLoc() const { return ContinueStmtBits.ContinueLoc; } - void setContinueLoc(SourceLocation L) { ContinueStmtBits.ContinueLoc = L; } + SourceLocation getContinueLoc() const { + return SourceLocation::getFromRawEncoding(ContinueStmtBits.ContinueLoc); + } + void setContinueLoc(SourceLocation L) { + ContinueStmtBits.ContinueLoc = L.getRawEncoding(); + } SourceLocation getBeginLoc() const { return getContinueLoc(); } SourceLocation getEndLoc() const { return getContinueLoc(); } @@ -3096,8 +3149,12 @@ class BreakStmt : public Stmt { /// Build an empty break statement. explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {} - SourceLocation getBreakLoc() const { return BreakStmtBits.BreakLoc; } - void setBreakLoc(SourceLocation L) { BreakStmtBits.BreakLoc = L; } + SourceLocation getBreakLoc() const { + return SourceLocation::getFromRawEncoding(BreakStmtBits.BreakLoc); + } + void setBreakLoc(SourceLocation L) { + BreakStmtBits.BreakLoc = L.getRawEncoding(); + } SourceLocation getBeginLoc() const { return getBreakLoc(); } SourceLocation getEndLoc() const { return getBreakLoc(); } @@ -3175,8 +3232,12 @@ class ReturnStmt final *getTrailingObjects() = Var; } - SourceLocation getReturnLoc() const { return ReturnStmtBits.RetLoc; } - void setReturnLoc(SourceLocation L) { ReturnStmtBits.RetLoc = L; } + SourceLocation getReturnLoc() const { + return SourceLocation::getFromRawEncoding(ReturnStmtBits.RetLoc); + } + void setReturnLoc(SourceLocation L) { + ReturnStmtBits.RetLoc = L.getRawEncoding(); + } SourceLocation getBeginLoc() const { return getReturnLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h index 7a0f5ba8d1270..f71dd282bdfdc 100644 --- a/clang/include/clang/Basic/SourceLocation.h +++ b/clang/include/clang/Basic/SourceLocation.h @@ -17,6 +17,7 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/MathExtras.h" #include #include #include @@ -84,7 +85,9 @@ class FileID { /// In addition, one bit of SourceLocation is used for quick access to the /// information whether the location is in a file or a macro expansion. /// -/// It is important that this type remains small. It is currently 32 bits wide. +/// It is important that this type remains small. +/// SourceLocation is 8 bytes, and internally only the lower `Bits` bits are +/// used. This means the total addressable source space to 2^(Bits - 1). class SourceLocation { friend class ASTReader; friend class ASTWriter; @@ -93,13 +96,15 @@ class SourceLocation { friend class SourceLocationEncoding; public: - using UIntTy = uint32_t; - using IntTy = int32_t; + using UIntTy = uint64_t; + using IntTy = int64_t; + // Number of bits used for the source space, one bit is preserved for MacroID. + static constexpr unsigned Bits = 40; private: - UIntTy ID = 0; + uint64_t ID = 0; - enum : UIntTy { MacroIDBit = 1ULL << (8 * sizeof(UIntTy) - 1) }; + enum : UIntTy { MacroIDBit = 1ULL << (Bits - 1) }; public: bool isFileID() const { return (ID & MacroIDBit) == 0; } @@ -142,7 +147,7 @@ class SourceLocation { } /// When a SourceLocation itself cannot be used, this returns - /// an (opaque) 32-bit integer encoding for it. + /// an (opaque) 64-bit integer encoding for it. /// /// This should only be passed to SourceLocation::getFromRawEncoding, it /// should not be inspected directly. @@ -158,6 +163,17 @@ class SourceLocation { return X; } + // APIs for 32-bit source location conversion. + // !! These are used *only* by libclang for backward compatibility. + // + // Returns true if this SourceLocation can be losslessly represented as + // a 32-bit integer. + bool getRawEncoding32(uint32_t &Result) const; + // Constructs a 64-bit SourceLocation from a 32-bit raw-encoded value, + // using the given SourceManager context. + static SourceLocation getFromRawEncoding32(const SourceManager &SM, + uint32_t Encoding32); + /// When a SourceLocation itself cannot be used, this returns /// an (opaque) pointer encoding for it. /// diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index cd3dac9133223..711b0fcbddd0b 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -742,10 +742,10 @@ class SourceManager : public RefCountedBase { /// not have been loaded, so that value would be unknown. SourceLocation::UIntTy CurrentLoadedOffset; - /// The highest possible offset is 2^31-1 (2^63-1 for 64-bit source - /// locations), so CurrentLoadedOffset starts at 2^31 (2^63 resp.). + /// The highest possible offset is 2^(Bits-1)-1, so CurrentLoadedOffset starts + /// at 2^(Bits-1). static const SourceLocation::UIntTy MaxLoadedOffset = - 1ULL << (8 * sizeof(SourceLocation::UIntTy) - 1); + 1ULL << (SourceLocation::Bits - 1); /// A bitmap that indicates whether the entries of LoadedSLocEntryTable /// have already been loaded from the external source. diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 7c66c26a17a13..449166881d207 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -72,7 +72,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { void CompleteRedeclChain(const Decl *D) override; /// Resolve a selector ID into a selector. - Selector GetExternalSelector(uint32_t ID) override; + Selector GetExternalSelector(uint64_t ID) override; /// Returns the number of selectors known to the external AST /// source. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 9d265f27b8e31..6a574744f675d 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -164,7 +164,9 @@ using LocalMacroID = uint32_t; const unsigned int NUM_PREDEF_MACRO_IDS = 1; /// An ID number that refers to an ObjC selector in an AST file. -using SelectorID = uint32_t; +using SelectorID = uint64_t; +static_assert(sizeof(SelectorID) >= sizeof(SourceLocation::UIntTy), + "SelectorID is too small to hold the SourceLocation"); /// The number of predefined selector IDs. const unsigned int NUM_PREDEF_SELECTOR_IDS = 1; diff --git a/clang/include/clang/Serialization/SourceLocationEncoding.h b/clang/include/clang/Serialization/SourceLocationEncoding.h index 5b2485dbc719f..06547b53a8aeb 100644 --- a/clang/include/clang/Serialization/SourceLocationEncoding.h +++ b/clang/include/clang/Serialization/SourceLocationEncoding.h @@ -15,17 +15,20 @@ // To achieve this, we need to encode the index of the module file into the // encoding of the source location. The encoding of the source location may be: // -// |-----------------------|-----------------------| -// | A | B | C | +// |---------------|---------------------------| +// | A | B | C | // -// * A: 32 bit. The index of the module file in the module manager + 1. The +1 +// * A: 24 bit. The index of the module file in the module manager + 1. The +1 // here is necessary since we wish 0 stands for the current module file. -// * B: 31 bit. The offset of the source location to the module file containing +// * B: 39 bit. The offset of the source location to the module file containing // it. // * C: The macro bit. We rotate it to the lowest bit so that we can save some // space in case the index of the module file is 0. // +// Together, B and C form SourceLocation::Bits (40 bits total). // +// Currently, only the lower 16 bits of A are used to store the module file +// index, leaving the upper 8 bits of A unused (reserved for future use). //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H @@ -43,17 +46,24 @@ namespace clang { // Macro locations have the top bit set, we rotate by one so it is the low bit. class SourceLocationEncoding { using UIntTy = SourceLocation::UIntTy; - constexpr static unsigned UIntBits = CHAR_BIT * sizeof(UIntTy); static UIntTy encodeRaw(UIntTy Raw) { - return (Raw << 1) | (Raw >> (UIntBits - 1)); + return ((Raw & llvm::maskTrailingOnes(SourceLocation::Bits - 1)) + << 1) | + (Raw >> (SourceLocation::Bits - 1)); } static UIntTy decodeRaw(UIntTy Raw) { - return (Raw >> 1) | (Raw << (UIntBits - 1)); + return (Raw >> 1) | ((Raw & 1) << (SourceLocation::Bits - 1)); } public: using RawLocEncoding = uint64_t; + // 16 bits should be sufficient to store the module file index. + constexpr static unsigned ModuleFileIndexBits = 16; + constexpr static unsigned SourceLocationEncodingBits = SourceLocation::Bits; + static_assert(ModuleFileIndexBits + SourceLocationEncodingBits < + sizeof(RawLocEncoding) * CHAR_BIT, + "Insufficient encoding bits"); static RawLocEncoding encode(SourceLocation Loc, UIntTy BaseOffset, unsigned BaseModuleFileIndex); @@ -77,20 +87,19 @@ SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset, Loc = Loc.getLocWithOffset(-BaseOffset); RawLocEncoding Encoded = encodeRaw(Loc.getRawEncoding()); - // 16 bits should be sufficient to store the module file index. - assert(BaseModuleFileIndex < (1 << 16)); - Encoded |= (RawLocEncoding)BaseModuleFileIndex << 32; + assert(BaseModuleFileIndex < (1 << ModuleFileIndexBits)); + Encoded |= (RawLocEncoding)BaseModuleFileIndex << SourceLocation::Bits; return Encoded; } inline std::pair SourceLocationEncoding::decode(RawLocEncoding Encoded) { - unsigned ModuleFileIndex = Encoded >> 32; + unsigned ModuleFileIndex = Encoded >> SourceLocation::Bits; if (!ModuleFileIndex) return {SourceLocation::getFromRawEncoding(decodeRaw(Encoded)), ModuleFileIndex}; - Encoded &= llvm::maskTrailingOnes(32); + Encoded &= llvm::maskTrailingOnes(SourceLocation::Bits); SourceLocation Loc = SourceLocation::getFromRawEncoding(decodeRaw(Encoded)); return {Loc, ModuleFileIndex}; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e7abb18330e17..db73c2c5674d7 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3200,6 +3200,15 @@ TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, return DI; } +CXXOperatorSourceInfo * +ASTContext::getCXXOperatorSourceInfo(SourceRange R) const { + auto *TInfo = (CXXOperatorSourceInfo *)BumpAlloc.Allocate( + sizeof(CXXOperatorSourceInfo), 8); + TInfo->BeginOpNameLoc = R.getBegin(); + TInfo->EndOpNameLoc = R.getEnd(); + return TInfo; +} + const ASTRecordLayout & ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const { return getObjCLayout(D); @@ -7096,7 +7105,7 @@ ASTContext::getNameForTemplate(TemplateName Name, DName = DeclarationNames.getCXXOperatorName(TN.getOperator()); // DNInfo work in progress: FIXME: source locations? DeclarationNameLoc DNLoc = - DeclarationNameLoc::makeCXXOperatorNameLoc(SourceRange()); + DeclarationNameLoc::makeCXXOperatorNameLoc(nullptr); return DeclarationNameInfo(DName, NameLoc, DNLoc); } } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 2b7d67f389a64..6b983c7744e52 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2071,7 +2071,8 @@ ASTNodeImporter::ImportDeclarationNameLoc( case DeclarationName::CXXOperatorName: { if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange())) - To.setCXXOperatorNameRange(*ToRangeOrErr); + To.setCXXOperatorNameInfo( + Importer.ToContext.getCXXOperatorSourceInfo(*ToRangeOrErr)); else return ToRangeOrErr.takeError(); return Error::success(); diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index ae5fcf6e86adf..430fa9372b3cf 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -387,7 +387,7 @@ DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { setNamedTypeLoc(nullptr); break; case DeclarationName::CXXOperatorName: - setCXXOperatorNameRange(SourceRange()); + CXXOperatorName.OInfo = nullptr; break; case DeclarationName::CXXLiteralOperatorName: setCXXLiteralOperatorNameLoc(SourceLocation()); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 51d83c480c2f1..c2f2e6bbd1536 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -441,7 +441,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; DeclRefExprBits.NonOdrUseReason = NOUR; DeclRefExprBits.IsImmediateEscalating = false; - DeclRefExprBits.Loc = L; + Loc = L; setDependence(computeDependence(this, Ctx)); } @@ -454,7 +454,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, QualType T, ExprValueKind VK, NonOdrUseReason NOUR) : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), DNLoc(NameInfo.getInfo()) { - DeclRefExprBits.Loc = NameInfo.getLoc(); + Loc = NameInfo.getLoc(); DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; if (QualifierLoc) new (getTrailingObjects()) @@ -618,7 +618,7 @@ PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, bool HasFunctionName = SL != nullptr; PredefinedExprBits.HasFunctionName = HasFunctionName; PredefinedExprBits.IsTransparent = IsTransparent; - PredefinedExprBits.Loc = L; + Loc = L; if (HasFunctionName) setFunctionName(SL); setDependence(computeDependence(this)); @@ -1467,7 +1467,7 @@ static unsigned SizeOfCallExprInstance(Expr::StmtClass SC) { // changing the size of SourceLocation, CallExpr, and // subclasses requires careful considerations -static_assert(sizeof(SourceLocation) == 4 && sizeof(CXXOperatorCallExpr) <= 32, +static_assert(sizeof(SourceLocation) == 8 && sizeof(CXXOperatorCallExpr) <= 32, "we assume CXXOperatorCallExpr is at most 32 bytes"); CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, @@ -1475,7 +1475,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs, ADLCallKind UsesADL) : Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) { - NumArgs = std::max(Args.size(), MinNumArgs); + CallExprBits.NumArgs = std::max(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); CallExprBits.NumPreArgs = NumPreArgs; assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); @@ -1489,7 +1489,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, setPreArg(I, PreArgs[I]); for (unsigned I = 0; I != Args.size(); ++I) setArg(I, Args[I]); - for (unsigned I = Args.size(); I != NumArgs; ++I) + for (unsigned I = Args.size(); I != CallExprBits.NumArgs; ++I) setArg(I, nullptr); this->computeDependence(); @@ -1505,7 +1505,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty) - : Expr(SC, Empty), NumArgs(NumArgs) { + : Expr(SC, Empty) { + CallExprBits.NumArgs = NumArgs; CallExprBits.NumPreArgs = NumPreArgs; assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); CallExprBits.HasFPFeatures = HasFPFeatures; @@ -1728,7 +1729,7 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, TemplateArgs || TemplateKWLoc.isValid(); MemberExprBits.HadMultipleCandidates = false; MemberExprBits.NonOdrUseReason = NOUR; - MemberExprBits.OperatorLoc = OperatorLoc; + this->OperatorLoc = OperatorLoc; if (hasQualifier()) new (getTrailingObjects()) @@ -4421,7 +4422,7 @@ GenericSelectionExpr::GenericSelectionExpr( " and TypeSourceInfo!"); assert(ResultIndex < NumAssocs && "ResultIndex is out-of-bounds!"); - GenericSelectionExprBits.GenericLoc = GenericLoc; + GenericSelectionExprBits.GenericLoc = GenericLoc.getRawEncoding(); getTrailingObjects()[getIndexOfControllingExpression()] = ControllingExpr; llvm::copy(AssocExprs, @@ -4448,7 +4449,7 @@ GenericSelectionExpr::GenericSelectionExpr( " and TypeSourceInfo!"); assert(ResultIndex < NumAssocs && "ResultIndex is out-of-bounds!"); - GenericSelectionExprBits.GenericLoc = GenericLoc; + GenericSelectionExprBits.GenericLoc = GenericLoc.getRawEncoding(); getTrailingObjects()[getIndexOfControllingType()] = ControllingType; llvm::copy(AssocExprs, @@ -4472,7 +4473,7 @@ GenericSelectionExpr::GenericSelectionExpr( "Must have the same number of association expressions" " and TypeSourceInfo!"); - GenericSelectionExprBits.GenericLoc = GenericLoc; + GenericSelectionExprBits.GenericLoc = GenericLoc.getRawEncoding(); getTrailingObjects()[getIndexOfControllingExpression()] = ControllingExpr; llvm::copy(AssocExprs, @@ -4496,7 +4497,7 @@ GenericSelectionExpr::GenericSelectionExpr( "Must have the same number of association expressions" " and TypeSourceInfo!"); - GenericSelectionExprBits.GenericLoc = GenericLoc; + GenericSelectionExprBits.GenericLoc = GenericLoc.getRawEncoding(); getTrailingObjects()[getIndexOfControllingType()] = ControllingType; llvm::copy(AssocExprs, @@ -4851,7 +4852,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, BinaryOperatorBits.Opc = opc; assert(!isCompoundAssignmentOp() && "Use CompoundAssignOperator for compound assignments"); - BinaryOperatorBits.OpLoc = opLoc; + this->OpLoc = opLoc; BinaryOperatorBits.ExcludedOverflowPattern = false; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -4871,7 +4872,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, BinaryOperatorBits.ExcludedOverflowPattern = false; assert(isCompoundAssignmentOp() && "Use CompoundAssignOperator for compound assignments"); - BinaryOperatorBits.OpLoc = opLoc; + this->OpLoc = opLoc; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); @@ -4938,7 +4939,7 @@ UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, : Expr(UnaryOperatorClass, type, VK, OK), Val(input) { UnaryOperatorBits.Opc = opc; UnaryOperatorBits.CanOverflow = CanOverflow; - UnaryOperatorBits.Loc = l; + this->Loc = l; UnaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); if (hasStoredFPFeatures()) setStoredFPFeatures(FPFeatures); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 685ef8baa70a3..1c832f11a8132 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1060,7 +1060,7 @@ CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, : VK_PRValue, /*FIXME*/ OK_Ordinary), Field(Field), UsedContext(UsedContext) { - CXXDefaultInitExprBits.Loc = Loc; + CXXDefaultInitExprBits.Loc = Loc.getRawEncoding(); CXXDefaultInitExprBits.HasRewrittenInit = RewrittenInitExpr != nullptr; if (CXXDefaultInitExprBits.HasRewrittenInit) @@ -1204,7 +1204,7 @@ CXXConstructExpr::CXXConstructExpr( CXXConstructExprBits.ZeroInitialization = ZeroInitialization; CXXConstructExprBits.ConstructionKind = llvm::to_underlying(ConstructKind); CXXConstructExprBits.IsImmediateEscalating = false; - CXXConstructExprBits.Loc = Loc; + this->Loc = Loc; Stmt **TrailingArgs = getTrailingArgs(); llvm::copy(Args, TrailingArgs); @@ -1508,7 +1508,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( (TemplateArgs != nullptr) || TemplateKWLoc.isValid(); CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr; - CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc; + CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc.getRawEncoding(); if (TemplateArgs) { auto Deps = TemplateArgumentDependence::None; diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index a2cf431a312af..df818922825cf 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -123,7 +123,7 @@ RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc), RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) { RequiresExprBits.IsSatisfied = false; - RequiresExprBits.RequiresKWLoc = RequiresKWLoc; + RequiresExprBits.RequiresKWLoc = RequiresKWLoc.getRawEncoding(); bool Dependent = false; bool ContainsUnexpandedParameterPack = false; for (ParmVarDecl *P : LocalParameters) { diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index e8c1004089713..9f714f8a8d455 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -72,7 +72,7 @@ bool ExternalASTSource::layoutRecordType( Decl *ExternalASTSource::GetExternalDecl(GlobalDeclID ID) { return nullptr; } -Selector ExternalASTSource::GetExternalSelector(uint32_t ID) { +Selector ExternalASTSource::GetExternalSelector(uint64_t ID) { return Selector(); } diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 4fc4a99ad2405..41c53f9be6027 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1072,7 +1072,7 @@ ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, SubExprs[COND] = Cond; SubExprs[INC] = Inc; SubExprs[BODY] = Body; - ForStmtBits.ForLoc = FL; + ForStmtBits.ForLoc = FL.getRawEncoding(); } VarDecl *ForStmt::getConditionVariable() const { diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp index c5b9864dbb33f..57fd17027f313 100644 --- a/clang/lib/Basic/SourceLocation.cpp +++ b/clang/lib/Basic/SourceLocation.cpp @@ -17,6 +17,8 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -48,6 +50,42 @@ static_assert(std::is_trivially_destructible_v, "SourceRange must be trivially destructible because it is " "used in unions"); +SourceLocation SourceLocation::getFromRawEncoding32(const SourceManager &SM, + uint32_t Encoding32) { + uint32_t Lower31Bits = Encoding32 & llvm::maskTrailingOnes(31); + uint64_t MacroBit = + (static_cast(Encoding32) & llvm::maskLeadingOnes(1)) + << (Bits - 32); + + if (Lower31Bits < SM.getNextLocalOffset()) { + // This is local offset, 32-to-64 offset mapping is identical. + UIntTy Raw64 = Lower31Bits | MacroBit; + return getFromRawEncoding(Raw64); + } + // Offset of loaded source location. + // 2^40 -> 2^31 + // 2^40 - 1 -> 2^31 - 1 + static constexpr uint64_t RangeMask = + llvm::maskTrailingOnes(Bits - 32) << 31; + return getFromRawEncoding(RangeMask | Lower31Bits | MacroBit); +} + +bool clang::SourceLocation::getRawEncoding32(uint32_t &Result) const { + // A mask that isolates this check to the required range higher of bits. + static constexpr uint64_t RangeMask = + llvm::maskTrailingOnes(Bits - 32) << 31; + + // Check if the ID can be safely compressed to a 32-bit integer. + // The truncation is only possible if all higher bits of the ID are all + // identical: + // all 0s for the local offset, or all 1s for loaded offset + if ((ID ^ (ID << 1)) & RangeMask) + return false; // won't fit + uint32_t Lower31Bits = ID & llvm::maskTrailingOnes(31); + // Restore the top macro bit. + return Result = Lower31Bits | ((ID & MacroIDBit) >> (Bits - 32)); +} + unsigned SourceLocation::getHashValue() const { return llvm::DenseMapInfo::getHashValue(ID); } diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 4aafac349e3e9..4a8dce8179eb3 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -288,7 +288,8 @@ class CoverageMappingBuilder { /// Return the start location of an included file or expanded macro. SourceLocation getStartOfFileOrMacro(SourceLocation Loc) { if (Loc.isMacroID()) - return Loc.getLocWithOffset(-SM.getFileOffset(Loc)); + return Loc.getLocWithOffset( + -static_cast(SM.getFileOffset(Loc))); return SM.getLocForStartOfFile(SM.getFileID(Loc)); } diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 06f68ec8b0fc1..9b0dda81f02a8 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1243,7 +1243,8 @@ FormatToken *FormatTokenLexer::getNextToken() { FormatTok = new (Allocator.Allocate()) FormatToken; readRawToken(*FormatTok); SourceLocation WhitespaceStart = - FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace); + FormatTok->Tok.getLocation().getLocWithOffset( + -static_cast(TrailingWhitespace)); FormatTok->IsFirst = IsFirstToken; IsFirstToken = false; diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 42ea7edf3aaad..f87c0b4a4ca60 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -580,7 +580,8 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc, return Loc; // Create a lexer starting at the beginning of this token. - SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second); + SourceLocation LexerStartLoc = Loc.getLocWithOffset( + -static_cast(LocInfo.second)); Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart, Buffer.end()); TheLexer.SetCommentRetentionState(true); @@ -623,7 +624,9 @@ SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc, SM.getDecomposedLoc(BeginFileLoc); assert(FileLocInfo.first == BeginFileLocInfo.first && FileLocInfo.second >= BeginFileLocInfo.second); - return Loc.getLocWithOffset(BeginFileLocInfo.second - FileLocInfo.second); + return Loc.getLocWithOffset( + static_cast(BeginFileLocInfo.second) - + FileLocInfo.second); } namespace { diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index 182907df56070..7b388e311f85a 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -183,7 +183,8 @@ ClangAsmParserCallback::translateLocation(const llvm::SourceMgr &LSM, if (TokIndex < AsmToks.size()) { const Token &Tok = AsmToks[TokIndex]; Loc = Tok.getLocation(); - Loc = Loc.getLocWithOffset(Offset - TokOffset); + Loc = Loc.getLocWithOffset(static_cast(Offset) - + TokOffset); } return Loc; } diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 9f19f13592e86..fa7cb3ec07b76 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -58,7 +58,7 @@ void MultiplexExternalSemaSource::CompleteRedeclChain(const Decl *D) { Sources[i]->CompleteRedeclChain(D); } -Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) { +Selector MultiplexExternalSemaSource::GetExternalSelector(uint64_t ID) { Selector Sel; for(size_t i = 0; i < Sources.size(); ++i) { Sel = Sources[i]->GetExternalSelector(ID); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e1cccf068b5aa..ffeeafefad41f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5914,11 +5914,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { } case UnqualifiedIdKind::IK_OperatorFunctionId: - NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( - Name.OperatorFunctionId.Operator)); - NameInfo.setCXXOperatorNameRange(SourceRange( - Name.OperatorFunctionId.SymbolLocations[0], Name.EndLocation)); - return NameInfo; + return DeclarationNameInfo( + Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator), + Name.StartLocation, + DeclarationNameLoc::makeCXXOperatorNameLoc( + Context.getCXXOperatorSourceInfo( + SourceRange(Name.OperatorFunctionId.SymbolLocations[0], + Name.EndLocation)))); case UnqualifiedIdKind::IK_LiteralOperatorId: NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 2c00616bc62d7..a47db06c3a2ab 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1003,8 +1003,8 @@ CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange, // and trailing-return-type respectively. DeclarationName MethodName = Context.DeclarationNames.getCXXOperatorName(OO_Call); - DeclarationNameLoc MethodNameLoc = - DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin()); + DeclarationNameLoc MethodNameLoc = DeclarationNameLoc::makeCXXOperatorNameLoc( + Context.getCXXOperatorSourceInfo(IntroducerRange.getBegin())); CXXMethodDecl *Method = CXXMethodDecl::Create( Context, Class, SourceLocation(), DeclarationNameInfo(MethodName, IntroducerRange.getBegin(), diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f5bdd903bcf5c..2bf9db724fd72 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15830,7 +15830,8 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators // CHECKME: no 'operator' keyword? DeclarationNameInfo OpNameInfo(OpName, LLoc); - OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); + OpNameInfo.setCXXOperatorNameInfo( + Context.getCXXOperatorSourceInfo(SourceRange(LLoc, RLoc))); ExprResult Fn = CreateUnresolvedLookupExpr( NamingClass, NestedNameSpecifierLoc(), OpNameInfo, UnresolvedSet<0>()); if (Fn.isInvalid()) @@ -15902,7 +15903,8 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Build the actual expression node. DeclarationNameInfo OpLocInfo(OpName, LLoc); - OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); + OpLocInfo.setCXXOperatorNameInfo( + Context.getCXXOperatorSourceInfo(SourceRange(LLoc, RLoc))); ExprResult FnExpr = CreateFunctionRefExpr( *this, FnDecl, Best->FoundDecl, Base, HadMultipleCandidates, OpLocInfo.getLoc(), OpLocInfo.getInfo()); @@ -16532,7 +16534,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, DeclarationNameInfo OpLocInfo( Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); - OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc)); + OpLocInfo.setCXXOperatorNameInfo( + Context.getCXXOperatorSourceInfo(SourceRange(LParenLoc, RParenLoc))); ExprResult NewFn = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, Obj, HadMultipleCandidates, OpLocInfo.getLoc(), diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 523165c6cab64..a0e86c6de11eb 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9792,7 +9792,8 @@ ASTRecordReader::readDeclarationNameLoc(DeclarationName Name) { return DeclarationNameLoc::makeNamedTypeLoc(readTypeSourceInfo()); case DeclarationName::CXXOperatorName: - return DeclarationNameLoc::makeCXXOperatorNameLoc(readSourceRange()); + return DeclarationNameLoc::makeCXXOperatorNameLoc( + getASTContext().getCXXOperatorSourceInfo(readSourceRange())); case DeclarationName::CXXLiteralOperatorName: return DeclarationNameLoc::makeCXXLiteralOperatorNameLoc( diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 0166e493bf03f..fabb679e1ee0a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -209,7 +209,7 @@ void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { assert(NumAttrs == Attrs.size()); std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr()); S->SubStmt = Record.readSubStmt(); - S->AttributedStmtBits.AttrLoc = readSourceLocation(); + S->AttrLoc = readSourceLocation(); } void ASTStmtReader::VisitIfStmt(IfStmt *S) { @@ -843,7 +843,8 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { VisitExpr(E); unsigned NumLocalParameters = Record.readInt(); unsigned NumRequirements = Record.readInt(); - E->RequiresExprBits.RequiresKWLoc = Record.readSourceLocation(); + E->RequiresExprBits.RequiresKWLoc = + Record.readSourceLocation().getRawEncoding(); E->RequiresExprBits.IsSatisfied = Record.readInt(); E->Body = Record.readDeclAs(); llvm::SmallVector LocalParameters; @@ -1071,7 +1072,7 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); - E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); + E->OperatorLoc = Record.readSourceLocation(); if (HasQualifier) new (E->getTrailingObjects()) @@ -1410,7 +1411,8 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { assert(NumAssocs == E->getNumAssocs() && "Wrong NumAssocs!"); E->IsExprPredicate = Record.readInt(); E->ResultIndex = Record.readInt(); - E->GenericSelectionExprBits.GenericLoc = readSourceLocation(); + E->GenericSelectionExprBits.GenericLoc = + readSourceLocation().getRawEncoding(); E->DefaultLoc = readSourceLocation(); E->RParenLoc = readSourceLocation(); @@ -1756,7 +1758,7 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->CXXConstructExprBits.ZeroInitialization = Record.readInt(); E->CXXConstructExprBits.ConstructionKind = Record.readInt(); E->CXXConstructExprBits.IsImmediateEscalating = Record.readInt(); - E->CXXConstructExprBits.Loc = readSourceLocation(); + E->Loc = readSourceLocation(); E->Constructor = readDeclAs(); E->ParenOrBraceRange = readSourceRange(); @@ -1880,7 +1882,7 @@ void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { VisitExpr(E); - E->CXXThrowExprBits.ThrowLoc = readSourceLocation(); + E->CXXThrowExprBits.ThrowLoc = readSourceLocation().getRawEncoding(); E->Operand = Record.readSubExpr(); E->CXXThrowExprBits.IsThrownVariableInScope = Record.readInt(); } @@ -1889,7 +1891,7 @@ void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { VisitExpr(E); E->Param = readDeclAs(); E->UsedContext = readDeclAs(); - E->CXXDefaultArgExprBits.Loc = readSourceLocation(); + E->CXXDefaultArgExprBits.Loc = readSourceLocation().getRawEncoding(); E->CXXDefaultArgExprBits.HasRewrittenInit = Record.readInt(); if (E->CXXDefaultArgExprBits.HasRewrittenInit) *E->getTrailingObjects() = Record.readSubExpr(); @@ -1900,7 +1902,7 @@ void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { E->CXXDefaultInitExprBits.HasRewrittenInit = Record.readInt(); E->Field = readDeclAs(); E->UsedContext = readDeclAs(); - E->CXXDefaultInitExprBits.Loc = readSourceLocation(); + E->CXXDefaultInitExprBits.Loc = readSourceLocation().getRawEncoding(); if (E->CXXDefaultInitExprBits.HasRewrittenInit) *E->getTrailingObjects() = Record.readSubExpr(); } @@ -1914,7 +1916,8 @@ void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { VisitExpr(E); E->TypeInfo = readTypeSourceInfo(); - E->CXXScalarValueInitExprBits.RParenLoc = readSourceLocation(); + E->CXXScalarValueInitExprBits.RParenLoc = + readSourceLocation().getRawEncoding(); } void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { @@ -1964,7 +1967,7 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { E->CXXDeleteExprBits.UsualArrayDeleteWantsSize = Record.readInt(); E->OperatorDelete = readDeclAs(); E->Argument = Record.readSubExpr(); - E->CXXDeleteExprBits.Loc = readSourceLocation(); + E->CXXDeleteExprBits.Loc = readSourceLocation().getRawEncoding(); } void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { @@ -2040,7 +2043,8 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr( else E->Base = nullptr; - E->CXXDependentScopeMemberExprBits.OperatorLoc = readSourceLocation(); + E->CXXDependentScopeMemberExprBits.OperatorLoc = + readSourceLocation().getRawEncoding(); if (HasFirstQualifierFoundInScope) *E->getTrailingObjects() = readDeclAs(); @@ -2227,7 +2231,8 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( E->Index = CurrentUnpackingBits->getNextBits(/*Width=*/12); E->PackIndex = Record.readUnsignedOrNone().toInternalRepresentation(); E->Final = CurrentUnpackingBits->getNextBit(); - E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation(); + E->SubstNonTypeTemplateParmExprBits.NameLoc = + readSourceLocation().getRawEncoding(); E->Replacement = Record.readSubExpr(); } @@ -2305,7 +2310,7 @@ void ASTStmtReader::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) { void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); E->SourceExpr = Record.readSubExpr(); - E->OpaqueValueExprBits.Loc = readSourceLocation(); + E->OpaqueValueExprBits.Loc = readSourceLocation().getRawEncoding(); E->setIsUnique(Record.readInt()); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index a5c81036d6d43..a0b628def74ae 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1022,7 +1022,7 @@ void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { } void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { - static_assert(DeclContext::NumObjCContainerDeclBits == 64, + static_assert(DeclContext::NumObjCContainerDeclBits == 53, "You need to update the serializer after you change the " "ObjCContainerDeclBits"); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index be9bad9e96cc1..418763309d951 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -514,7 +514,7 @@ void ASTStmtWriter::VisitRequiresExpr(RequiresExpr *E) { VisitExpr(E); Record.push_back(E->getLocalParameters().size()); Record.push_back(E->getRequirements().size()); - Record.AddSourceLocation(E->RequiresExprBits.RequiresKWLoc); + Record.AddSourceLocation(E->getRequiresKWLoc()); Record.push_back(E->RequiresExprBits.IsSatisfied); Record.AddDeclRef(E->getBody()); for (ParmVarDecl *P : E->getLocalParameters()) diff --git a/clang/test/Lexer/SourceLocationsOverflow.c b/clang/test/Lexer/SourceLocationsOverflow.c deleted file mode 100644 index 26b0d204c49ff..0000000000000 --- a/clang/test/Lexer/SourceLocationsOverflow.c +++ /dev/null @@ -1,38 +0,0 @@ -// RUN: not %clang %s -S -o - 2>&1 | FileCheck %s -// CHECK: In file included from {{.*}}SourceLocationsOverflow.c -// CHECK-NEXT: inc1.h{{.*}}: fatal error: translation unit is too large for Clang to process: ran out of source locations -// CHECK-NEXT: #include "inc2.h" -// CHECK-NEXT: ^ -// CHECK-NEXT: note: 214{{.......}}B (2.15GB) in local locations, 0B (0B) in locations loaded from AST files, for a total of 214{{.......}}B (2.15GB) (99% of available space) -// CHECK-NEXT: {{.*}}inc2.h:1:1: note: file entered 214{{..}} times using 214{{.......}}B (2.15GB) of space -// CHECK-NEXT: /*................................................................................................. -// CHECK-NEXT: ^ -// CHECK-NEXT: {{.*}}inc1.h:1:1: note: file entered 15 times using 39{{....}}B (396.92kB) of space -// CHECK-NEXT: #include "inc2.h" -// CHECK-NEXT: ^ -// CHECK-NEXT: :1:1: note: file entered {{.*}} times using {{.*}}B ({{.*}}B) of space -// CHECK-NEXT: # {{.*}} -// CHECK-NEXT: ^ -// CHECK-NEXT: {{.*}}SourceLocationsOverflow.c:1:1: note: file entered 1 time using {{.*}}B ({{.*}}B) of space -// CHECK-NEXT: // RUN: not %clang %s -S -o - 2>&1 | FileCheck %s -// CHECK-NEXT: ^ -// CHECK-NEXT: 1 error generated. -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" -#include "Inputs/inc1.h" diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e239ffae547aa..841c42d7c3445 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -166,16 +166,21 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM, Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc), SM, LangOpts); EndLoc = EndLoc.getLocWithOffset(Length); } - - CXSourceRange Result = { - {&SM, &LangOpts}, R.getBegin().getRawEncoding(), EndLoc.getRawEncoding()}; + unsigned BeginRaw, EndRaw; + if (!R.getBegin().getRawEncoding32(BeginRaw) || + !EndLoc.getRawEncoding32(EndRaw)) + return clang_getNullRange(); // location is too big for libclang ABI + CXSourceRange Result = {{&SM, &LangOpts}, BeginRaw, EndRaw}; return Result; } CharSourceRange cxloc::translateCXRangeToCharRange(CXSourceRange R) { + if (!R.ptr_data[0]) + return CharSourceRange(); + const SourceManager &SM = *static_cast(R.ptr_data[0]); return CharSourceRange::getCharRange( - SourceLocation::getFromRawEncoding(R.begin_int_data), - SourceLocation::getFromRawEncoding(R.end_int_data)); + SourceLocation::getFromRawEncoding32(SM, R.begin_int_data), + SourceLocation::getFromRawEncoding32(SM, R.end_int_data)); } //===----------------------------------------------------------------------===// @@ -2122,7 +2127,9 @@ class MemberRefVisit : public VisitorJob { return static_cast(data[0]); } SourceLocation getLoc() const { - return SourceLocation::getFromRawEncoding( + // this->get()->getASTContext().getSourceManager(); + return SourceLocation::getFromRawEncoding32( + this->get()->getASTContext().getSourceManager(), (SourceLocation::UIntTy)(uintptr_t)data[1]); } }; @@ -7635,9 +7642,15 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { if (!CXXUnit) return cxstring::createEmpty(); +<<<<<<< HEAD SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]); std::pair LocInfo = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); +======= + SourceLocation Loc = SourceLocation::getFromRawEncoding32( + CXXUnit->getSourceManager(), CXTok.int_data[1]); + auto LocInfo = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); +>>>>>>> de04b79aa72e (64-bit source location) bool Invalid = false; StringRef Buffer = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); @@ -7659,7 +7672,8 @@ CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) { return cxloc::translateSourceLocation( CXXUnit->getASTContext(), - SourceLocation::getFromRawEncoding(CXTok.int_data[1])); + SourceLocation::getFromRawEncoding32(CXXUnit->getSourceManager(), + CXTok.int_data[1])); } CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) { @@ -7674,10 +7688,11 @@ CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) { return cxloc::translateSourceRange( CXXUnit->getASTContext(), - SourceLocation::getFromRawEncoding(CXTok.int_data[1])); + SourceLocation::getFromRawEncoding32(CXXUnit->getSourceManager(), + CXTok.int_data[1])); } -static void getTokens(ASTUnit *CXXUnit, SourceRange Range, +static bool getTokens(ASTUnit *CXXUnit, SourceRange Range, SmallVectorImpl &CXTokens) { SourceManager &SourceMgr = CXXUnit->getSourceManager(); std::pair BeginLocInfo = @@ -7687,13 +7702,13 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range, // Cannot tokenize across files. if (BeginLocInfo.first != EndLocInfo.first) - return; + return false; // Create a lexer bool Invalid = false; StringRef Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); if (Invalid) - return; + return false; Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), CXXUnit->getASTContext().getLangOpts(), Buffer.begin(), @@ -7714,7 +7729,11 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range, CXToken CXTok; // - Common fields - CXTok.int_data[1] = Tok.getLocation().getRawEncoding(); + uint32_t TokLocRaw; + if (!Tok.getLocation().getRawEncoding32(TokLocRaw)) + return false; // location is too big for libclang ABI + CXTok.int_data[1] = TokLocRaw; + CXTok.int_data[2] = Tok.getLength(); CXTok.int_data[3] = 0; @@ -7743,6 +7762,8 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range, CXTokens.push_back(CXTok); previousWasAt = Tok.is(tok::at); } while (Lex.getBufferLocation() < EffectiveBufferEnd); + + return true; } CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) { @@ -7769,7 +7790,8 @@ CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) { SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second); SmallVector CXTokens; - getTokens(CXXUnit, SourceRange(Begin, End), CXTokens); + if (!getTokens(CXXUnit, SourceRange(Begin, End), CXTokens)) + return nullptr; if (CXTokens.empty()) return nullptr; @@ -7806,7 +7828,8 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens, return; SmallVector CXTokens; - getTokens(CXXUnit, R, CXTokens); + if (!getTokens(CXXUnit, R, CXTokens)) + return; if (CXTokens.empty()) return; @@ -7870,13 +7893,15 @@ class AnnotateTokensWorker { unsigned NextToken() const { return TokIdx; } void AdvanceToken() { ++TokIdx; } SourceLocation GetTokenLoc(unsigned tokI) { - return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]); + return SourceLocation::getFromRawEncoding32(SrcMgr, + getTok(tokI).int_data[1]); } bool isFunctionMacroToken(unsigned tokI) const { return getTok(tokI).int_data[3] != 0; } SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const { - return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[3]); + return SourceLocation::getFromRawEncoding32(SrcMgr, + getTok(tokI).int_data[3]); } void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange); @@ -8371,13 +8396,16 @@ class MarkMacroArgTokensVisitor { } SourceLocation getTokenLoc(unsigned tokI) { - return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]); + return SourceLocation::getFromRawEncoding32(SM, getTok(tokI).int_data[1]); } void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) { // The third field is reserved and currently not used. Use it here // to mark macro arg expanded tokens with their expanded locations. - getTok(tokI).int_data[3] = loc.getRawEncoding(); + uint32_t Raw; + if (!loc.getRawEncoding32(Raw)) + Raw = 0; // invalid source location + getTok(tokI).int_data[3] = Raw; } }; @@ -8437,8 +8465,8 @@ static void annotatePreprocessorTokens(CXTranslationUnit TU, if (lexNext(Lex, Tok, NextIdx, NumTokens)) break; unsigned TokIdx = NextIdx - 1; - assert(Tok.getLocation() == - SourceLocation::getFromRawEncoding(Tokens[TokIdx].int_data[1])); + assert(Tok.getLocation() == SourceLocation::getFromRawEncoding32( + SourceMgr, Tokens[TokIdx].int_data[1])); reprocess: if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { @@ -8488,8 +8516,8 @@ static void annotatePreprocessorTokens(CXTranslationUnit TU, unsigned LastIdx = finished ? NextIdx - 1 : NextIdx - 2; assert(TokIdx <= LastIdx); - SourceLocation EndLoc = - SourceLocation::getFromRawEncoding(Tokens[LastIdx].int_data[1]); + SourceLocation EndLoc = SourceLocation::getFromRawEncoding32( + SourceMgr, Tokens[LastIdx].int_data[1]); CXCursor Cursor = MakePreprocessingDirectiveCursor(SourceRange(BeginLoc, EndLoc), TU); diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index 2b2e70d60d1d6..a3c781592ca11 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -988,8 +988,8 @@ bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD, const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i]; if (baseInfo->base) { const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl; - SourceLocation - Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data); + SourceLocation Loc = SourceLocation::getFromRawEncoding32( + Ctx->getSourceManager(), baseInfo->loc.int_data); markEntityOccurrenceInFile(BaseD, Loc); } } @@ -1077,9 +1077,11 @@ CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 }; if (Loc.isInvalid()) return idxLoc; - + uint32_t LocRaw; + if (!Loc.getRawEncoding32(LocRaw)) + return idxLoc; idxLoc.ptr_data[0] = const_cast(this); - idxLoc.int_data = Loc.getRawEncoding(); + idxLoc.int_data = LocRaw; return idxLoc; } diff --git a/clang/tools/libclang/CXSourceLocation.cpp b/clang/tools/libclang/CXSourceLocation.cpp index cd41e9f0d6403..a5df9ca71ae34 100644 --- a/clang/tools/libclang/CXSourceLocation.cpp +++ b/clang/tools/libclang/CXSourceLocation.cpp @@ -211,24 +211,27 @@ static void createNullLocation(CXString *filename, unsigned *line, } int clang_Location_isInSystemHeader(CXSourceLocation location) { + if (!location.ptr_data[0]) + return 0; + const SourceManager &SM = + *static_cast(location.ptr_data[0]); const SourceLocation Loc = - SourceLocation::getFromRawEncoding(location.int_data); + SourceLocation::getFromRawEncoding32(SM, location.int_data); if (Loc.isInvalid()) return 0; - const SourceManager &SM = - *static_cast(location.ptr_data[0]); return SM.isInSystemHeader(Loc); } int clang_Location_isFromMainFile(CXSourceLocation location) { + if (!location.ptr_data[0]) + return 0; + const SourceManager &SM = + *static_cast(location.ptr_data[0]); const SourceLocation Loc = - SourceLocation::getFromRawEncoding(location.int_data); + SourceLocation::getFromRawEncoding32(SM, location.int_data); if (Loc.isInvalid()) return 0; - - const SourceManager &SM = - *static_cast(location.ptr_data[0]); return SM.isWrittenInMainFile(Loc); } @@ -241,16 +244,21 @@ void clang_getExpansionLocation(CXSourceLocation location, CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset); return; } + if (!location.ptr_data[0]) { + createNullLocation(file, line, column, offset); + return; + } - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); + const SourceManager &SM = + *static_cast(location.ptr_data[0]); + SourceLocation Loc = + SourceLocation::getFromRawEncoding32(SM, location.int_data); - if (!location.ptr_data[0] || Loc.isInvalid()) { + if (Loc.isInvalid()) { createNullLocation(file, line, column, offset); return; } - const SourceManager &SM = - *static_cast(location.ptr_data[0]); SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); // Check that the FileID is invalid on the expansion location. @@ -283,16 +291,21 @@ void clang_getPresumedLocation(CXSourceLocation location, createNullLocation(filename, line, column); return; } - - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - - if (!location.ptr_data[0] || Loc.isInvalid()) { + if (!location.ptr_data[0]) { createNullLocation(filename, line, column); return; } const SourceManager &SM = *static_cast(location.ptr_data[0]); + SourceLocation Loc = + SourceLocation::getFromRawEncoding32(SM, location.int_data); + + if (Loc.isInvalid()) { + createNullLocation(filename, line, column); + return; + } + PresumedLoc PreLoc = SM.getPresumedLoc(Loc); if (PreLoc.isInvalid()) { createNullLocation(filename, line, column); @@ -323,14 +336,16 @@ void clang_getSpellingLocation(CXSourceLocation location, column, offset); return; } - - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - - if (!location.ptr_data[0] || Loc.isInvalid()) + if (!location.ptr_data[0]) return createNullLocation(file, line, column, offset); - const SourceManager &SM = - *static_cast(location.ptr_data[0]); + *static_cast(location.ptr_data[0]); + SourceLocation Loc = + SourceLocation::getFromRawEncoding32(SM, location.int_data); + + if (Loc.isInvalid()) + return createNullLocation(file, line, column, offset); + SourceLocation SpellLoc = SM.getSpellingLoc(Loc); std::pair LocInfo = SM.getDecomposedLoc(SpellLoc); FileID FID = LocInfo.first; @@ -360,13 +375,17 @@ void clang_getFileLocation(CXSourceLocation location, return; } - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - - if (!location.ptr_data[0] || Loc.isInvalid()) + if (!location.ptr_data[0]) return createNullLocation(file, line, column, offset); const SourceManager &SM = - *static_cast(location.ptr_data[0]); + *static_cast(location.ptr_data[0]); + SourceLocation Loc = + SourceLocation::getFromRawEncoding32(SM, location.int_data); + + if (Loc.isInvalid()) + return createNullLocation(file, line, column, offset); + SourceLocation FileLoc = SM.getFileLoc(Loc); std::pair LocInfo = SM.getDecomposedLoc(FileLoc); FileID FID = LocInfo.first; diff --git a/clang/tools/libclang/CXSourceLocation.h b/clang/tools/libclang/CXSourceLocation.h index c86f6850375bb..d514b0448d538 100644 --- a/clang/tools/libclang/CXSourceLocation.h +++ b/clang/tools/libclang/CXSourceLocation.h @@ -30,9 +30,15 @@ translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation Loc) { if (Loc.isInvalid()) return clang_getNullLocation(); + uint32_t LocRaw; + if (!Loc.getRawEncoding32(LocRaw)) + return clang_getNullLocation(); // location is too big for libclang ABI - CXSourceLocation Result = { { &SM, &LangOpts, }, - Loc.getRawEncoding() }; + CXSourceLocation Result = {{ + &SM, + &LangOpts, + }, + LocRaw}; return Result; } @@ -63,12 +69,20 @@ static inline CXSourceRange translateSourceRange(ASTContext &Context, } static inline SourceLocation translateSourceLocation(CXSourceLocation L) { - return SourceLocation::getFromRawEncoding(L.int_data); + if (!L.ptr_data[0]) { + return SourceLocation(); + } + const SourceManager &SM = *static_cast(L.ptr_data[0]); + return SourceLocation::getFromRawEncoding32(SM, L.int_data); } static inline SourceRange translateCXSourceRange(CXSourceRange R) { - return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data), - SourceLocation::getFromRawEncoding(R.end_int_data)); + if (!R.ptr_data[0]) { + return SourceRange(); + } + const SourceManager &SM = *static_cast(R.ptr_data[0]); + return SourceRange(SourceLocation::getFromRawEncoding32(SM, R.begin_int_data), + SourceLocation::getFromRawEncoding32(SM, R.end_int_data)); } /// Translates CXSourceRange to CharSourceRange. diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 3cd49bf90235b..b6220466472cd 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -979,23 +979,30 @@ void clang_indexLoc_getFileLocation(CXIdxLoc location, if (file) *file = nullptr; if (line) *line = 0; if (column) *column = 0; - if (offset) *offset = 0; - - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - if (!location.ptr_data[0] || Loc.isInvalid()) + if (offset) + *offset = 0; + if (!location.ptr_data[0]) return; - CXIndexDataConsumer &DataConsumer = - *static_cast(location.ptr_data[0]); + *static_cast(location.ptr_data[0]); + SourceLocation Loc = SourceLocation::getFromRawEncoding32( + DataConsumer.getASTContext().getSourceManager(), location.int_data); + if (Loc.isInvalid()) + return; + DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); } CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { - SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - if (!location.ptr_data[0] || Loc.isInvalid()) + if (!location.ptr_data[0]) return clang_getNullLocation(); CXIndexDataConsumer &DataConsumer = - *static_cast(location.ptr_data[0]); + *static_cast(location.ptr_data[0]); + const auto &SM = DataConsumer.getASTContext().getSourceManager(); + SourceLocation Loc = + SourceLocation::getFromRawEncoding32(SM, location.int_data); + if (Loc.isInvalid()) + return clang_getNullLocation(); return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); } diff --git a/clang/unittests/Lex/PPMemoryAllocationsTest.cpp b/clang/unittests/Lex/PPMemoryAllocationsTest.cpp index 4d83003e28b36..7b36d5f3326e9 100644 --- a/clang/unittests/Lex/PPMemoryAllocationsTest.cpp +++ b/clang/unittests/Lex/PPMemoryAllocationsTest.cpp @@ -87,7 +87,7 @@ TEST_F(PPMemoryAllocationsTest, PPMacroDefinesAllocations) { // Assume a reasonable upper bound based on that number that we don't want // to exceed when storing information about a macro #define with 1 or 3 // tokens. - EXPECT_LT(BytesPerDefine, 130.0f); + EXPECT_LT(BytesPerDefine, 150.0f); } } // anonymous namespace diff --git a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp index 18fedd4de3973..9b201aa14ec97 100644 --- a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp +++ b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/SourceLocationEncoding.h" +#include "llvm/Support/MathExtras.h" #include "gtest/gtest.h" #include @@ -46,6 +47,8 @@ TEST(SourceLocationEncoding, Individual) { roundTrip(Big + 1); roundTrip(MacroBit | Big); roundTrip(MacroBit | (Big + 1)); + roundTrip(Biggest); + roundTrip(MacroBit | Biggest); } } // namespace From 09d4fd340b7beaf20ce805f01171e21d890b3845 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 8 Jul 2025 09:26:17 +0200 Subject: [PATCH 06/15] Fix merge conflicts --- clang/tools/libclang/CIndex.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 841c42d7c3445..5d4a2cf7fa146 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -7642,15 +7642,9 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { if (!CXXUnit) return cxstring::createEmpty(); -<<<<<<< HEAD - SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]); - std::pair LocInfo = - CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); -======= SourceLocation Loc = SourceLocation::getFromRawEncoding32( CXXUnit->getSourceManager(), CXTok.int_data[1]); auto LocInfo = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); ->>>>>>> de04b79aa72e (64-bit source location) bool Invalid = false; StringRef Buffer = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); From 55df4a1898ff091652bfbc253da59733179dd88d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 8 Jul 2025 09:41:32 +0200 Subject: [PATCH 07/15] Fix tests --- .../unittests/Serialization/SourceLocationEncodingTest.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp index 9b201aa14ec97..0c36feef6386f 100644 --- a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp +++ b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp @@ -34,9 +34,10 @@ void roundTrip(SourceLocation::UIntTy Loc, ASSERT_EQ(DecodedEncoded, Loc) << "Decoding " << ActualEncoded; } -constexpr SourceLocation::UIntTy MacroBit = - 1 << (sizeof(SourceLocation::UIntTy) * CHAR_BIT - 1); -constexpr SourceLocation::UIntTy Big = MacroBit >> 1; +constexpr SourceLocation::UIntTy MacroBit = 1ull << (SourceLocation::Bits - 1); +constexpr SourceLocation::UIntTy Big = 1ull << (SourceLocation::Bits - 2); +constexpr SourceLocation::UIntTy Biggest = + llvm::maskTrailingOnes(SourceLocation::Bits - 1); TEST(SourceLocationEncoding, Individual) { roundTrip(1, 2); From ac75b5741d65bccb1b4dd3756cbe4d805043e8b5 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 8 Jul 2025 11:44:59 +0200 Subject: [PATCH 08/15] Fix lldb build --- lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h | 4 ++-- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h index a1f02dc3d1b09..f2b95aa5ffb66 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h @@ -44,7 +44,7 @@ class ExternalASTSourceWrapper : public clang::ExternalSemaSource { return m_Source->GetExternalDecl(ID); } - clang::Selector GetExternalSelector(uint32_t ID) override { + clang::Selector GetExternalSelector(uint64_t ID) override { return m_Source->GetExternalSelector(ID); } @@ -339,7 +339,7 @@ class SemaSourceWithPriorities : public clang::ExternalSemaSource { Sources[i]->CompleteRedeclChain(D); } - clang::Selector GetExternalSelector(uint32_t ID) override { + clang::Selector GetExternalSelector(uint64_t ID) override { clang::Selector Sel; for (size_t i = 0; i < Sources.size(); ++i) { Sel = Sources[i]->GetExternalSelector(ID); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index dd89bae96f629..ce7b8173152ef 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -51,7 +51,7 @@ class ClangASTSource : public clang::ExternalASTSource, /// Interface stubs. clang::Decl *GetExternalDecl(clang::GlobalDeclID) override { return nullptr; } clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; } - clang::Selector GetExternalSelector(uint32_t) override { + clang::Selector GetExternalSelector(uint64_t) override { return clang::Selector(); } uint32_t GetNumExternalSelectors() override { return 0; } From 532432ffbec56e9d1ef49401500a2f9b37024e6c Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Thu, 3 Jul 2025 15:37:55 -0700 Subject: [PATCH 09/15] [Modules] Record side effect info in EvaluatedStmt (#146468) All deserialized VarDecl initializers are EvaluatedStmt, but not all EvaluatedStmt initializers are from a PCH. Calling `VarDecl::hasInitWithSideEffects` can trigger constant evaluation, but it's hard to know ahead of time whether that will trigger deserialization - even if the initializer is fully deserialized, it may contain a call to a constructor whose body is not deserialized. By caching the result of `VarDecl::hasInitWithSideEffects` and populating that cache during deserialization we can guarantee that calling it won't trigger deserialization regardless of the state of the initializer. This also reduces memory usage by removing the `InitSideEffectVars` set in `ASTReader`. rdar://154717930 --- clang/include/clang/AST/Decl.h | 14 +++-- clang/include/clang/AST/ExternalASTSource.h | 15 ------ .../clang/Sema/MultiplexExternalSemaSource.h | 2 - clang/include/clang/Serialization/ASTReader.h | 8 --- clang/lib/AST/Decl.cpp | 28 ++++------ .../lib/Sema/MultiplexExternalSemaSource.cpp | 8 --- clang/lib/Serialization/ASTReader.cpp | 4 -- clang/lib/Serialization/ASTReaderDecl.cpp | 5 +- clang/lib/Serialization/ASTWriter.cpp | 4 ++ clang/lib/Serialization/ASTWriterDecl.cpp | 1 - .../var-init-side-effects-modulemap.cpp | 51 +++++++++++++++++++ 11 files changed, 77 insertions(+), 63 deletions(-) create mode 100644 clang/test/Modules/var-init-side-effects-modulemap.cpp diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index c4202f1f3d07e..f70a039bf3517 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -888,13 +888,17 @@ struct EvaluatedStmt { bool HasICEInit : 1; bool CheckedForICEInit : 1; + bool HasSideEffects : 1; + bool CheckedForSideEffects : 1; + LazyDeclStmtPtr Value; APValue Evaluated; EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), HasConstantInitialization(false), HasConstantDestruction(false), - HasICEInit(false), CheckedForICEInit(false) {} + HasICEInit(false), CheckedForICEInit(false), HasSideEffects(false), + CheckedForSideEffects(false) {} }; /// Represents a variable declaration or definition. @@ -1353,9 +1357,11 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { return const_cast(this)->getInitializingDeclaration(); } - /// Checks whether this declaration has an initializer with side effects, - /// without triggering deserialization if the initializer is not yet - /// deserialized. + /// Checks whether this declaration has an initializer with side effects. + /// The result is cached. If the result hasn't been computed this can trigger + /// deserialization and constant evaluation. By running this during + /// serialization and serializing the result all clients can safely call this + /// without triggering further deserialization. bool hasInitWithSideEffects() const; /// Determine whether this variable's value might be usable in a diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 01dd56b576200..d7fdcaef922b3 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -196,10 +196,6 @@ class ExternalASTSource : public RefCountedBase { /// module. virtual bool wasThisDeclarationADefinition(const FunctionDecl *FD); - virtual bool hasInitializerWithSideEffects(const VarDecl *VD) const { - return false; - } - /// Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// @@ -434,17 +430,6 @@ struct LazyOffsetPtr { return GetPtr(); } - /// Retrieve the pointer to the AST node that this lazy pointer points to, - /// if it can be done without triggering deserialization. - /// - /// \returns a pointer to the AST node, or null if not yet deserialized. - T *getWithoutDeserializing() const { - if (isOffset()) { - return nullptr; - } - return GetPtr(); - } - /// Retrieve the address of the AST node pointer. Deserializes the pointee if /// necessary. T **getAddressOfPointer(ExternalASTSource *Source) const { diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 449166881d207..343ca63f43d5f 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -94,8 +94,6 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { bool wasThisDeclarationADefinition(const FunctionDecl *FD) override; - bool hasInitializerWithSideEffects(const VarDecl *VD) const override; - /// Find all declarations with the given name in the /// given context. bool FindExternalVisibleDeclsByName(const DeclContext *DC, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 43b4576093cf4..3d96f8e65180d 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1453,12 +1453,6 @@ class ASTReader const StringRef &operator*() && = delete; }; - /// VarDecls with initializers containing side effects must be emitted, - /// but DeclMustBeEmitted is not allowed to deserialize the intializer. - /// FIXME: Lower memory usage by removing VarDecls once the initializer - /// is deserialized. - llvm::SmallPtrSet InitSideEffectVars; - public: /// Get the buffer for resolving paths. SmallString<0> &getPathBuf() { return PathBuf; } @@ -2410,8 +2404,6 @@ class ASTReader bool wasThisDeclarationADefinition(const FunctionDecl *FD) override; - bool hasInitializerWithSideEffects(const VarDecl *VD) const override; - /// Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index bc88045c17f73..60a9a23722a0f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2445,24 +2445,16 @@ bool VarDecl::hasInitWithSideEffects() const { if (!hasInit()) return false; - // Check if we can get the initializer without deserializing - const Expr *E = nullptr; - if (auto *S = dyn_cast(Init)) { - E = cast(S); - } else { - E = cast_or_null(getEvaluatedStmt()->Value.getWithoutDeserializing()); - } - - if (E) - return E->HasSideEffects(getASTContext()) && - // We can get a value-dependent initializer during error recovery. - (E->isValueDependent() || !evaluateValue()); - - assert(getEvaluatedStmt()->Value.isOffset()); - // ASTReader tracks this without having to deserialize the initializer - if (auto Source = getASTContext().getExternalSource()) - return Source->hasInitializerWithSideEffects(this); - return false; + EvaluatedStmt *ES = ensureEvaluatedStmt(); + if (!ES->CheckedForSideEffects) { + const Expr *E = getInit(); + ES->HasSideEffects = + E->HasSideEffects(getASTContext()) && + // We can get a value-dependent initializer during error recovery. + (E->isValueDependent() || !evaluateValue()); + ES->CheckedForSideEffects = true; + } + return ES->HasSideEffects; } bool VarDecl::isOutOfLine() const { diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index fa7cb3ec07b76..17aa43b6c84b8 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -115,14 +115,6 @@ bool MultiplexExternalSemaSource::wasThisDeclarationADefinition( return false; } -bool MultiplexExternalSemaSource::hasInitializerWithSideEffects( - const VarDecl *VD) const { - for (const auto &S : Sources) - if (S->hasInitializerWithSideEffects(VD)) - return true; - return false; -} - bool MultiplexExternalSemaSource::FindExternalVisibleDeclsByName( const DeclContext *DC, DeclarationName Name, const DeclContext *OriginalDC) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a0e86c6de11eb..cd57409867ba0 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9725,10 +9725,6 @@ bool ASTReader::wasThisDeclarationADefinition(const FunctionDecl *FD) { return ThisDeclarationWasADefinitionSet.contains(FD); } -bool ASTReader::hasInitializerWithSideEffects(const VarDecl *VD) const { - return InitSideEffectVars.count(VD); -} - Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { return DecodeSelector(getGlobalSelectorID(M, LocalID)); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0ffd78424be0d..8bde213dc4cb3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1628,9 +1628,6 @@ RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = VarDeclBits.getNextBit(); - if (VarDeclBits.getNextBit()) - Reader.InitSideEffectVars.insert(VD); - VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit(); HasDeducedType = VarDeclBits.getNextBit(); VD->NonParmVarDeclBits.ImplicitParamKind = @@ -1701,6 +1698,8 @@ void ASTDeclReader::ReadVarDeclInit(VarDecl *VD) { Eval->HasConstantInitialization = (Val & 2) != 0; Eval->HasConstantDestruction = (Val & 4) != 0; Eval->WasEvaluated = (Val & 8) != 0; + Eval->HasSideEffects = (Val & 16) != 0; + Eval->CheckedForSideEffects = true; if (Eval->WasEvaluated) { Eval->Evaluated = Record.readAPValue(); if (Eval->Evaluated.needsCleanup()) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 874b24b532b06..2bd9ae50b72e7 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7320,6 +7320,10 @@ void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) { uint64_t Val = 1; if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) { + // This may trigger evaluation, so run it first + if (VD->hasInitWithSideEffects()) + Val |= 16; + assert(ES->CheckedForSideEffects); Val |= (ES->HasConstantInitialization ? 2 : 0); Val |= (ES->HasConstantDestruction ? 4 : 0); APValue *Evaluated = VD->getEvaluatedValue(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index a0b628def74ae..562ac7bc1835d 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1306,7 +1306,6 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VarDeclBits.addBit(D->isConstexpr()); VarDeclBits.addBit(D->isInitCapture()); VarDeclBits.addBit(D->isPreviousDeclInSameBlockScope()); - VarDeclBits.addBit(D->hasInitWithSideEffects()); VarDeclBits.addBit(D->isEscapingByref()); HasDeducedType = D->getType()->getContainedDeducedType(); diff --git a/clang/test/Modules/var-init-side-effects-modulemap.cpp b/clang/test/Modules/var-init-side-effects-modulemap.cpp new file mode 100644 index 0000000000000..750a6f1731405 --- /dev/null +++ b/clang/test/Modules/var-init-side-effects-modulemap.cpp @@ -0,0 +1,51 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/module.modulemap %t/test.cppm -I%t +// + +//--- test.cppm +#pragma clang module import Baz + +//--- Foo.h +#pragma once +class foo { + char dummy = 1; + +public: + static foo var; + +}; + +inline foo foo::var; + +//--- Bar.h +#pragma once +#include + +void bar() { + (void) foo::var; +} + +//--- Baz.h +#pragma once +#include + +void baz() { + (void) foo::var; +} + +#include + +//--- module.modulemap +module Foo { + header "Foo.h" +} +module Bar { + header "Bar.h" +} +module Baz { + header "Baz.h" +} + From 960aaa4c30fe451c38c07f06bc32b2f32db81e99 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 7 Jul 2025 16:01:40 -0700 Subject: [PATCH 10/15] [Modules] Don't const eval VarDecls with dependent type (#147378) EvaluateAsInitializer does not support evaluating values with dependent types. This was previously guarded with a check for the initializer expression, but it is possible for the VarDecl to have a dependent type without the initializer having a dependent type, when the initializer is a specialized template type and the VarDecl has the unspecialized type. This adds a guard checking for dependence in the VarDecl type as well. This fixes the issue raised by Google in https://github.com/llvm/llvm-project/pull/145447 --- clang/lib/AST/Decl.cpp | 3 ++- .../var-init-side-effects-templated.cpp | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 clang/test/Modules/var-init-side-effects-templated.cpp diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 60a9a23722a0f..adf6c050109d9 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2451,7 +2451,8 @@ bool VarDecl::hasInitWithSideEffects() const { ES->HasSideEffects = E->HasSideEffects(getASTContext()) && // We can get a value-dependent initializer during error recovery. - (E->isValueDependent() || !evaluateValue()); + (E->isValueDependent() || getType()->isDependentType() || + !evaluateValue()); ES->CheckedForSideEffects = true; } return ES->HasSideEffects; diff --git a/clang/test/Modules/var-init-side-effects-templated.cpp b/clang/test/Modules/var-init-side-effects-templated.cpp new file mode 100644 index 0000000000000..542ca270429b6 --- /dev/null +++ b/clang/test/Modules/var-init-side-effects-templated.cpp @@ -0,0 +1,20 @@ +// Tests referencing variable with initializer containing side effect across module boundary + +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -o %t + +export module Foo; + +export template +struct Wrapper { + double value; +}; + +export constexpr Wrapper Compute() { + return Wrapper{1.0}; +} + +export template +Wrapper ComputeInFloat() { + const Wrapper a = Compute(); + return a; +} From 86eca472e9ca3e4b0719eca5d7a97943e86a1055 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 1 Jul 2025 21:59:09 +0200 Subject: [PATCH 11/15] [clang] Improve getFileIDLocal binary search. (#146510) Avoid reading the `LocalSLocEntryTable` twice per loop iteration. NFC. https://llvm-compile-time-tracker.com/compare.php?from=0b6ddb02efdcbdac9426e8d857499ea0580303cd&to=1aa335ccfb07ba96177b89b1933aa6b980fa14f6&stat=instructions:u --- clang/lib/Basic/SourceManager.cpp | 41 ++++++++++++------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 053e82683a4a6..16703ca194364 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -812,6 +812,8 @@ FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const { /// loaded one. FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { assert(SLocOffset < NextLocalOffset && "Bad function choice"); + assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && + "Invalid SLocOffset"); // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file @@ -855,35 +857,24 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { break; } - NumProbes = 0; - while (true) { - unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; - SourceLocation::UIntTy MidOffset = - getLocalSLocEntry(MiddleIndex).getOffset(); - - ++NumProbes; - - // If the offset of the midpoint is too large, chop the high side of the - // range to the midpoint. - if (MidOffset > SLocOffset) { - GreaterIndex = MiddleIndex; - continue; - } + while (LessIndex < GreaterIndex) { + ++NumBinaryProbes; - // If the middle index contains the value, succeed and return. - if (MiddleIndex + 1 == LocalSLocEntryTable.size() || - SLocOffset < getLocalSLocEntry(MiddleIndex + 1).getOffset()) { - FileID Res = FileID::get(MiddleIndex); + unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2; - // Remember it. We have good locality across FileID lookups. - LastFileIDLookup = Res; - NumBinaryProbes += NumProbes; - return Res; - } + SourceLocation::UIntTy MidOffset = + LocalSLocEntryTable[MiddleIndex].getOffset(); - // Otherwise, move the low-side up to the middle index. - LessIndex = MiddleIndex; + if (MidOffset <= SLocOffset) + LessIndex = MiddleIndex + 1; + else + GreaterIndex = MiddleIndex; } + + // At this point, LessIndex is the index of the *first element greater than* + // SLocOffset. The element we are actually looking for is the one immediately + // before it. + return LastFileIDLookup = FileID::get(LessIndex - 1); } /// Return the FileID for a SourceLocation with a high offset. From 3881fb941c67c6ded8ea7b3f7b743f0b726e787c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 4 Jul 2025 22:11:59 +0200 Subject: [PATCH 12/15] [clang] SourceManager: Cache offsets for LastFileIDLookup to speed up getFileID (#146782) `getFileID` is a hot method. By caching the offset range in `LastFileIDLookup`, we can more quickly check whether a given offset falls within it, avoiding calling `isOffsetInFileID`. https://llvm-compile-time-tracker.com/compare.php?from=0588e8188c647460b641b09467fe6b13a8d510d5&to=64843a500f0191b79a8109da9acd7e80d961c7a3&stat=instructions:u --- clang/include/clang/Basic/SourceManager.h | 5 +++-- clang/lib/Basic/SourceManager.cpp | 27 +++++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 711b0fcbddd0b..6d4cbd552da43 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -767,6 +767,8 @@ class SourceManager : public RefCountedBase { /// LastFileIDLookup records the last FileID looked up or created, because it /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; + mutable SourceLocation::UIntTy LastLookupStartOffset; + mutable SourceLocation::UIntTy LastLookupEndOffset; // exclude /// Holds information for \#line directives. /// @@ -1904,9 +1906,8 @@ class SourceManager : public RefCountedBase { FileID getFileID(SourceLocation::UIntTy SLocOffset) const { // If our one-entry cache covers this offset, just return it. - if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) + if (SLocOffset >= LastLookupStartOffset && SLocOffset < LastLookupEndOffset) return LastFileIDLookup; - return getFileIDSlow(SLocOffset); } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 16703ca194364..266e66a9d85e2 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -335,6 +335,7 @@ void SourceManager::clearIDTables() { LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = nullptr; LastFileIDLookup = FileID(); + LastLookupStartOffset = LastLookupEndOffset = 0; IncludedLocMap.clear(); if (LineTable) @@ -640,9 +641,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, LocalSLocEntryTable.push_back( SLocEntry::get(NextLocalOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename))); + LastLookupStartOffset = NextLocalOffset; // We do a +1 here because we want a SourceLocation that means "the end of the // file", e.g. for the "no newline at the end of the file" diagnostic. NextLocalOffset += FileSize + 1; + LastLookupEndOffset = NextLocalOffset; updateSlocUsageStats(); // Set LastFileIDLookup to the newly created file. The next getFileID call is @@ -812,8 +815,9 @@ FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const { /// loaded one. FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { assert(SLocOffset < NextLocalOffset && "Bad function choice"); - assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && + assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 && "Invalid SLocOffset"); + assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry"); // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file @@ -833,13 +837,11 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { unsigned LessIndex = 0; // upper bound of the search range. unsigned GreaterIndex = LocalSLocEntryTable.size(); - if (LastFileIDLookup.ID >= 0) { - // Use the LastFileIDLookup to prune the search space. - if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) - LessIndex = LastFileIDLookup.ID; - else - GreaterIndex = LastFileIDLookup.ID; - } + // Use the LastFileIDLookup to prune the search space. + if (LastLookupStartOffset < SLocOffset) + LessIndex = LastFileIDLookup.ID; + else + GreaterIndex = LastFileIDLookup.ID; // Find the FileID that contains this. unsigned NumProbes = 0; @@ -850,7 +852,12 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { FileID Res = FileID::get(int(GreaterIndex)); // Remember it. We have good locality across FileID lookups. LastFileIDLookup = Res; - NumLinearScans += NumProbes+1; + LastLookupStartOffset = LocalSLocEntryTable[GreaterIndex].getOffset(); + LastLookupEndOffset = + GreaterIndex + 1 >= LocalSLocEntryTable.size() + ? NextLocalOffset + : LocalSLocEntryTable[GreaterIndex + 1].getOffset(); + NumLinearScans += NumProbes + 1; return Res; } if (++NumProbes == 8) @@ -874,6 +881,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { // At this point, LessIndex is the index of the *first element greater than* // SLocOffset. The element we are actually looking for is the one immediately // before it. + LastLookupStartOffset = LocalSLocEntryTable[LessIndex - 1].getOffset(); + LastLookupEndOffset = LocalSLocEntryTable[LessIndex].getOffset(); return LastFileIDLookup = FileID::get(LessIndex - 1); } From 8ece0b12aad75da30498ef05c0164ceb3b5772ed Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 7 Jul 2025 09:42:38 +0200 Subject: [PATCH 13/15] [clang] Speedup getFileIDLocal with a separate offset table. (#146604) The `SLocEntry` structure is 24 bytes, and the binary search only needs the offset. Loading an entry's offset might pull the entire SLocEntry object into the CPU cache. To make the binary search much more cache-efficient, we use a separate offset table. See https://llvm-compile-time-tracker.com/compare.php?from=650d0151c623c123e4e9736fe50421624a329260&to=6af564c0d75aff28a2784a8554448c0679877792&stat=instructions:u. --- clang/include/clang/Basic/SourceManager.h | 2 ++ clang/lib/Basic/SourceManager.cpp | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 6d4cbd552da43..30982f3a39907 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -719,6 +719,8 @@ class SourceManager : public RefCountedBase { /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid /// expansion. SmallVector LocalSLocEntryTable; + /// An in-parallel offset table, merely used for speeding up FileID lookup. + SmallVector LocalLocOffsetTable; /// The table of SLocEntries that are loaded from other modules. /// diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 266e66a9d85e2..09b19658eb576 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -329,6 +329,7 @@ SourceManager::~SourceManager() { void SourceManager::clearIDTables() { MainFileID = FileID(); LocalSLocEntryTable.clear(); + LocalLocOffsetTable.clear(); LoadedSLocEntryTable.clear(); SLocEntryLoaded.clear(); SLocEntryOffsetLoaded.clear(); @@ -638,9 +639,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, noteSLocAddressSpaceUsage(Diag); return FileID(); } + assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size()); LocalSLocEntryTable.push_back( SLocEntry::get(NextLocalOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename))); + LocalLocOffsetTable.push_back(NextLocalOffset); LastLookupStartOffset = NextLocalOffset; // We do a +1 here because we want a SourceLocation that means "the end of the // file", e.g. for the "no newline at the end of the file" diagnostic. @@ -694,7 +697,9 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true; return SourceLocation::getMacroLoc(LoadedOffset); } + assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size()); LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); + LocalLocOffsetTable.push_back(NextLocalOffset); if (NextLocalOffset + Length + 1 <= NextLocalOffset || NextLocalOffset + Length + 1 > CurrentLoadedOffset) { Diag.Report(diag::err_sloc_space_too_large); @@ -817,6 +822,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { assert(SLocOffset < NextLocalOffset && "Bad function choice"); assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 && "Invalid SLocOffset"); + assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size()); assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry"); // After the first and second level caches, I see two common sorts of @@ -847,8 +853,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { unsigned NumProbes = 0; while (true) { --GreaterIndex; - assert(GreaterIndex < LocalSLocEntryTable.size()); - if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) { + assert(GreaterIndex < LocalLocOffsetTable.size()); + if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) { FileID Res = FileID::get(int(GreaterIndex)); // Remember it. We have good locality across FileID lookups. LastFileIDLookup = Res; @@ -868,11 +874,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { ++NumBinaryProbes; unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2; - - SourceLocation::UIntTy MidOffset = - LocalSLocEntryTable[MiddleIndex].getOffset(); - - if (MidOffset <= SLocOffset) + if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset) LessIndex = MiddleIndex + 1; else GreaterIndex = MiddleIndex; From f3c4f721f9978119d432799588e4b01c2beb624c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 15 Jul 2025 13:43:50 +0200 Subject: [PATCH 14/15] [clang] Reduce the size of ParsedAttributesView and AttributePool (#148726) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These objects are used as local stack variables during parsing, and they are not small. This patch reduces their sizes: * `ParsedAttributesView`: 72 → 40 bytes * `AttributePool`: 72 → 40 bytes No negative performance impact has been [observed](https://llvm-compile-time-tracker.com/compare.php?from=a709621cd545b061782b03136286227867b452a6&to=f50500b3c178e97c0c861301e853e6d5b859040b&stat=instructions:u). **Context:** We have some verilator-generated code with extremely deep nesting of parenthesized expressions, e.g.: ```cpp bool s = (...(bool)(i[0]) |(bool)(i[1])) |(bool)(i[2])) | ... |(bool)(i[n])); ``` Before this patch, on my local machine, Clang begins emitting `-Wstack-exhausted` when `n` is 715. After the patch, that threshold increases to `950`. --- clang/include/clang/Sema/ParsedAttr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 6b3c5a173417a..9accd28137661 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -678,7 +678,7 @@ class AttributePool { friend class AttributeFactory; friend class ParsedAttributes; AttributeFactory &Factory; - llvm::SmallVector Attrs; + llvm::SmallVector Attrs; void *allocate(size_t size) { return Factory.allocate(size); @@ -808,7 +808,7 @@ class AttributePool { class ParsedAttributesView { friend class AttributePool; - using VecTy = llvm::SmallVector; + using VecTy = llvm::SmallVector; using SizeType = decltype(std::declval().size()); public: From 8c98fefebad3f66ae9d4feafdf8e1dff6f656edd Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 15 Jul 2025 13:44:24 +0200 Subject: [PATCH 15/15] [clang] Reduce the small vector size for DeclTypeInfo. (#148788) The `Declarator` class is large (4584 bytes) and used as a stack-local variable during parsing. This patch reduces the default size of its `DeclTypeInfo` member, reducing the overall size down to 3880 bytes. This allows clang handle more deeply nested expressions without exhausting the stack. Combined with #148726, the nesting threshold for such expressions increases to `~1100`. No performance impact being [observed](https://llvm-compile-time-tracker.com/compare.php?from=d4f5ed6a23464cbe831820cb695aa1d39b11e4aa&to=66ba54b8a295cc2759387ef2a4a162de2ad4946e&stat=instructions:u). --- clang/include/clang/Sema/DeclSpec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 6c4a32c4ac2f0..4f63e8a88d849 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1918,7 +1918,7 @@ class Declarator { /// parsed. This is pushed from the identifier out, which means that element /// #0 will be the most closely bound to the identifier, and /// DeclTypeInfo.back() will be the least closely bound. - SmallVector DeclTypeInfo; + SmallVector DeclTypeInfo; /// InvalidType - Set by Sema::GetTypeForDeclarator(). LLVM_PREFERRED_TYPE(bool)