diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-10-16 19:03:40 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:05:09 +0000 |
commit | 6246ae0b85d8159978c01ae916a9ad6cde9378b5 (patch) | |
tree | 4e95c640a44c343a08cf21d58972d36bd342e4ce /contrib/llvm-project/clang/lib | |
parent | a4a491e2238b12ccd64d3faf9e6401487f6f1f1b (diff) | |
parent | dafdd7863e9eeed3a714329b8758451cbcfc33bf (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib')
6 files changed, 199 insertions, 84 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp index 8d778500d103..625048c69a86 100644 --- a/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp @@ -1993,7 +1993,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs(); assert(Args); - if (Args->size() != 1) { + if (Args->size() != 1 || Args->get(0).getKind() != TemplateArgument::Pack) { const TemplateParameterList *TPL = nullptr; if (!DRE->hadMultipleCandidates()) if (const auto *TD = dyn_cast<TemplateDecl>(DRE->getDecl())) diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp index 481438de0e53..9935fcc0d3ea 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp @@ -1509,6 +1509,21 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S, llvm::ConstantInt *CaseVal = Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); + + // Emit debuginfo for the case value if it is an enum value. + const ConstantExpr *CE; + if (auto ICE = dyn_cast<ImplicitCastExpr>(S.getLHS())) + CE = dyn_cast<ConstantExpr>(ICE->getSubExpr()); + else + CE = dyn_cast<ConstantExpr>(S.getLHS()); + if (CE) { + if (auto DE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) + if (CGDebugInfo *Dbg = getDebugInfo()) + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) + Dbg->EmitGlobalVariable(DE->getDecl(), + APValue(llvm::APSInt(CaseVal->getValue()))); + } + if (SwitchLikelihood) SwitchLikelihood->push_back(Stmt::getLikelihood(Attrs)); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp index 0fe084b628da..836aabf80179 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1377,19 +1377,23 @@ struct CounterCoverageMappingBuilder // Extend into the condition before we propagate through it below - this is // needed to handle macros that generate the "if" but not the condition. - extendRegion(S->getCond()); + if (!S->isConsteval()) + extendRegion(S->getCond()); Counter ParentCount = getRegion().getCounter(); Counter ThenCount = getRegionCounter(S); - // Emitting a counter for the condition makes it easier to interpret the - // counter for the body when looking at the coverage. - propagateCounts(ParentCount, S->getCond()); + if (!S->isConsteval()) { + // Emitting a counter for the condition makes it easier to interpret the + // counter for the body when looking at the coverage. + propagateCounts(ParentCount, S->getCond()); - // The 'then' count applies to the area immediately after the condition. - auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); + // The 'then' count applies to the area immediately after the condition. + Optional<SourceRange> Gap = + findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); + if (Gap) + fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); + } extendRegion(S->getThen()); Counter OutCount = propagateCounts(ThenCount, S->getThen()); @@ -1398,9 +1402,9 @@ struct CounterCoverageMappingBuilder if (const Stmt *Else = S->getElse()) { bool ThenHasTerminateStmt = HasTerminateStmt; HasTerminateStmt = false; - // The 'else' count applies to the area immediately after the 'then'. - Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); + Optional<SourceRange> Gap = + findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); extendRegion(Else); @@ -1416,9 +1420,11 @@ struct CounterCoverageMappingBuilder GapRegionCounter = OutCount; } - // Create Branch Region around condition. - createBranchRegion(S->getCond(), ThenCount, - subtractCounters(ParentCount, ThenCount)); + if (!S->isConsteval()) { + // Create Branch Region around condition. + createBranchRegion(S->getCond(), ThenCount, + subtractCounters(ParentCount, ThenCount)); + } } void VisitCXXTryStmt(const CXXTryStmt *S) { diff --git a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp index d3b454843234..bf7ca718a36b 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp @@ -695,10 +695,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, // member of reference type uninitialized, the program is // ill-formed. SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) - << Field->getType() - << ILE->getSyntacticForm()->getSourceRange(); - SemaRef.Diag(Field->getLocation(), - diag::note_uninit_reference_member); + << Field->getType() + << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm()) + ->getSourceRange(); + SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); } hadError = true; return; diff --git a/contrib/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/contrib/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp index 0143b5f8df6b..655be20572b6 100644 --- a/contrib/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp +++ b/contrib/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp @@ -165,8 +165,8 @@ struct TransferableCommand { const unsigned OldPos = Pos; std::unique_ptr<llvm::opt::Arg> Arg(OptTable.ParseOneArg( ArgList, Pos, - /* Include */ ClangCLMode ? CoreOption | CLOption : 0, - /* Exclude */ ClangCLMode ? 0 : CLOption)); + /* Include */ ClangCLMode ? CoreOption | CLOption | CLDXCOption : 0, + /* Exclude */ ClangCLMode ? 0 : CLOption | CLDXCOption)); if (!Arg) continue; diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp index e2014f965c90..1fa73c667b7f 100644 --- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp +++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp @@ -55,45 +55,140 @@ getTokensCovering(llvm::ArrayRef<syntax::Token> Toks, SourceRange R, return {Begin, End}; } -// Finds the smallest expansion range that contains expanded tokens First and -// Last, e.g.: +// Finds the range within FID corresponding to expanded tokens [First, Last]. +// Prev precedes First and Next follows Last, these must *not* be included. +// If no range satisfies the criteria, returns an invalid range. +// // #define ID(x) x // ID(ID(ID(a1) a2)) // ~~ -> a1 // ~~ -> a2 // ~~~~~~~~~ -> a1 a2 -SourceRange findCommonRangeForMacroArgs(const syntax::Token &First, - const syntax::Token &Last, - const SourceManager &SM) { - SourceRange Res; - auto FirstLoc = First.location(), LastLoc = Last.location(); - // Keep traversing up the spelling chain as longs as tokens are part of the - // same expansion. - while (!FirstLoc.isFileID() && !LastLoc.isFileID()) { - auto ExpInfoFirst = SM.getSLocEntry(SM.getFileID(FirstLoc)).getExpansion(); - auto ExpInfoLast = SM.getSLocEntry(SM.getFileID(LastLoc)).getExpansion(); - // Stop if expansions have diverged. - if (ExpInfoFirst.getExpansionLocStart() != - ExpInfoLast.getExpansionLocStart()) +SourceRange spelledForExpandedSlow(SourceLocation First, SourceLocation Last, + SourceLocation Prev, SourceLocation Next, + FileID TargetFile, + const SourceManager &SM) { + // There are two main parts to this algorithm: + // - identifying which spelled range covers the expanded tokens + // - validating that this range doesn't cover any extra tokens (First/Last) + // + // We do these in order. However as we transform the expanded range into the + // spelled one, we adjust First/Last so the validation remains simple. + + assert(SM.getSLocEntry(TargetFile).isFile()); + // In most cases, to select First and Last we must return their expansion + // range, i.e. the whole of any macros they are included in. + // + // When First and Last are part of the *same macro arg* of a macro written + // in TargetFile, we that slice of the arg, i.e. their spelling range. + // + // Unwrap such macro calls. If the target file has A(B(C)), the + // SourceLocation stack of a token inside C shows us the expansion of A first, + // then B, then any macros inside C's body, then C itself. + // (This is the reverse of the order the PP applies the expansions in). + while (First.isMacroID() && Last.isMacroID()) { + auto DecFirst = SM.getDecomposedLoc(First); + auto DecLast = SM.getDecomposedLoc(Last); + auto &ExpFirst = SM.getSLocEntry(DecFirst.first).getExpansion(); + auto &ExpLast = SM.getSLocEntry(DecLast.first).getExpansion(); + + if (!ExpFirst.isMacroArgExpansion() || !ExpLast.isMacroArgExpansion()) + break; + // Locations are in the same macro arg if they expand to the same place. + // (They may still have different FileIDs - an arg can have >1 chunks!) + if (ExpFirst.getExpansionLocStart() != ExpLast.getExpansionLocStart()) break; - // Do not continue into macro bodies. - if (!ExpInfoFirst.isMacroArgExpansion() || - !ExpInfoLast.isMacroArgExpansion()) + // Careful, given: + // #define HIDE ID(ID(a)) + // ID(ID(HIDE)) + // The token `a` is wrapped in 4 arg-expansions, we only want to unwrap 2. + // We distinguish them by whether the macro expands into the target file. + // Fortunately, the target file ones will always appear first. + auto &ExpMacro = + SM.getSLocEntry(SM.getFileID(ExpFirst.getExpansionLocStart())) + .getExpansion(); + if (ExpMacro.getExpansionLocStart().isMacroID()) break; - FirstLoc = SM.getImmediateSpellingLoc(FirstLoc); - LastLoc = SM.getImmediateSpellingLoc(LastLoc); - // Update the result afterwards, as we want the tokens that triggered the - // expansion. - Res = {FirstLoc, LastLoc}; + // Replace each endpoint with its spelling inside the macro arg. + // (This is getImmediateSpellingLoc without repeating lookups). + First = ExpFirst.getSpellingLoc().getLocWithOffset(DecFirst.second); + Last = ExpLast.getSpellingLoc().getLocWithOffset(DecLast.second); + + // Now: how do we adjust the previous/next bounds? Three cases: + // A) If they are also part of the same macro arg, we translate them too. + // This will ensure that we don't select any macros nested within the + // macro arg that cover extra tokens. Critical case: + // #define ID(X) X + // ID(prev target) // selecting 'target' succeeds + // #define LARGE ID(prev target) + // LARGE // selecting 'target' fails. + // B) They are not in the macro at all, then their expansion range is a + // sibling to it, and we can safely substitute that. + // #define PREV prev + // #define ID(X) X + // PREV ID(target) // selecting 'target' succeeds. + // #define LARGE PREV ID(target) + // LARGE // selecting 'target' fails. + // C) They are in a different arg of this macro, or the macro body. + // Now selecting the whole macro arg is fine, but the whole macro is not. + // Model this by setting using the edge of the macro call as the bound. + // #define ID2(X, Y) X Y + // ID2(prev, target) // selecting 'target' succeeds + // #define LARGE ID2(prev, target) + // LARGE // selecting 'target' fails + auto AdjustBound = [&](SourceLocation &Bound) { + if (Bound.isInvalid() || !Bound.isMacroID()) // Non-macro must be case B. + return; + auto DecBound = SM.getDecomposedLoc(Bound); + auto &ExpBound = SM.getSLocEntry(DecBound.first).getExpansion(); + if (ExpBound.isMacroArgExpansion() && + ExpBound.getExpansionLocStart() == ExpFirst.getExpansionLocStart()) { + // Case A: translate to (spelling) loc within the macro arg. + Bound = ExpBound.getSpellingLoc().getLocWithOffset(DecBound.second); + return; + } + while (Bound.isMacroID()) { + SourceRange Exp = SM.getImmediateExpansionRange(Bound).getAsRange(); + if (Exp.getBegin() == ExpMacro.getExpansionLocStart()) { + // Case B: bounds become the macro call itself. + Bound = (&Bound == &Prev) ? Exp.getBegin() : Exp.getEnd(); + return; + } + // Either case C, or expansion location will later find case B. + // We choose the upper bound for Prev and the lower one for Next: + // ID(prev) target ID(next) + // ^ ^ + // new-prev new-next + Bound = (&Bound == &Prev) ? Exp.getEnd() : Exp.getBegin(); + } + }; + AdjustBound(Prev); + AdjustBound(Next); } - // Normally mapping back to expansion location here only changes FileID, as - // we've already found some tokens expanded from the same macro argument, and - // they should map to a consecutive subset of spelled tokens. Unfortunately - // SourceManager::isBeforeInTranslationUnit discriminates sourcelocations - // based on their FileID in addition to offsets. So even though we are - // referring to same tokens, SourceManager might tell us that one is before - // the other if they've got different FileIDs. - return SM.getExpansionRange(CharSourceRange(Res, true)).getAsRange(); + + // In all remaining cases we need the full containing macros. + // If this overlaps Prev or Next, then no range is possible. + SourceRange Candidate = + SM.getExpansionRange(SourceRange(First, Last)).getAsRange(); + auto DecFirst = SM.getDecomposedExpansionLoc(Candidate.getBegin()); + auto DecLast = SM.getDecomposedLoc(Candidate.getEnd()); + // Can end up in the wrong file due to bad input or token-pasting shenanigans. + if (Candidate.isInvalid() || DecFirst.first != TargetFile || DecLast.first != TargetFile) + return SourceRange(); + // Check bounds, which may still be inside macros. + if (Prev.isValid()) { + auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Prev).getBegin()); + if (Dec.first != DecFirst.first || Dec.second >= DecFirst.second) + return SourceRange(); + } + if (Next.isValid()) { + auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Next).getEnd()); + if (Dec.first != DecLast.first || Dec.second <= DecLast.second) + return SourceRange(); + } + // Now we know that Candidate is a file range that covers [First, Last] + // without encroaching on {Prev, Next}. Ship it! + return Candidate; } } // namespace @@ -363,51 +458,50 @@ TokenBuffer::spelledForExpanded(llvm::ArrayRef<syntax::Token> Expanded) const { // of the range, bail out in that case. if (Expanded.empty()) return llvm::None; - - const syntax::Token *BeginSpelled; - const Mapping *BeginMapping; - std::tie(BeginSpelled, BeginMapping) = - spelledForExpandedToken(&Expanded.front()); - - const syntax::Token *LastSpelled; - const Mapping *LastMapping; - std::tie(LastSpelled, LastMapping) = - spelledForExpandedToken(&Expanded.back()); - - FileID FID = SourceMgr->getFileID(BeginSpelled->location()); + const syntax::Token *First = &Expanded.front(); + const syntax::Token *Last = &Expanded.back(); + const syntax::Token *FirstSpelled, *LastSpelled; + const TokenBuffer::Mapping *FirstMapping, *LastMapping; + std::tie(FirstSpelled, FirstMapping) = spelledForExpandedToken(First); + std::tie(LastSpelled, LastMapping) = spelledForExpandedToken(Last); + + FileID FID = SourceMgr->getFileID(FirstSpelled->location()); // FIXME: Handle multi-file changes by trying to map onto a common root. if (FID != SourceMgr->getFileID(LastSpelled->location())) return llvm::None; const MarkedFile &File = Files.find(FID)->second; - // If both tokens are coming from a macro argument expansion, try and map to - // smallest part of the macro argument. BeginMapping && LastMapping check is - // only for performance, they are a prerequisite for Expanded.front() and - // Expanded.back() being part of a macro arg expansion. - if (BeginMapping && LastMapping && - SourceMgr->isMacroArgExpansion(Expanded.front().location()) && - SourceMgr->isMacroArgExpansion(Expanded.back().location())) { - auto CommonRange = findCommonRangeForMacroArgs(Expanded.front(), - Expanded.back(), *SourceMgr); - // It might be the case that tokens are arguments of different macro calls, - // in that case we should continue with the logic below instead of returning - // an empty range. - if (CommonRange.isValid()) - return getTokensCovering(File.SpelledTokens, CommonRange, *SourceMgr); + // If the range is within one macro argument, the result may be only part of a + // Mapping. We must use the general (SourceManager-based) algorithm. + if (FirstMapping && FirstMapping == LastMapping && + SourceMgr->isMacroArgExpansion(First->location()) && + SourceMgr->isMacroArgExpansion(Last->location())) { + // We use excluded Prev/Next token for bounds checking. + SourceLocation Prev = (First == &ExpandedTokens.front()) + ? SourceLocation() + : (First - 1)->location(); + SourceLocation Next = (Last == &ExpandedTokens.back()) + ? SourceLocation() + : (Last + 1)->location(); + SourceRange Range = spelledForExpandedSlow( + First->location(), Last->location(), Prev, Next, FID, *SourceMgr); + if (Range.isInvalid()) + return llvm::None; + return getTokensCovering(File.SpelledTokens, Range, *SourceMgr); } + // Otherwise, use the fast version based on Mappings. // Do not allow changes that doesn't cover full expansion. - unsigned BeginExpanded = Expanded.begin() - ExpandedTokens.data(); - unsigned EndExpanded = Expanded.end() - ExpandedTokens.data(); - if (BeginMapping && BeginExpanded != BeginMapping->BeginExpanded) + unsigned FirstExpanded = Expanded.begin() - ExpandedTokens.data(); + unsigned LastExpanded = Expanded.end() - ExpandedTokens.data(); + if (FirstMapping && FirstExpanded != FirstMapping->BeginExpanded) return llvm::None; - if (LastMapping && LastMapping->EndExpanded != EndExpanded) + if (LastMapping && LastMapping->EndExpanded != LastExpanded) return llvm::None; - // All is good, return the result. return llvm::makeArrayRef( - BeginMapping ? File.SpelledTokens.data() + BeginMapping->BeginSpelled - : BeginSpelled, + FirstMapping ? File.SpelledTokens.data() + FirstMapping->BeginSpelled + : FirstSpelled, LastMapping ? File.SpelledTokens.data() + LastMapping->EndSpelled : LastSpelled + 1); } |