diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTConcept.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Program.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Analysis/ExprMutationAnalyzer.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Format/WhitespaceManager.cpp | 118 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 44 |
5 files changed, 83 insertions, 106 deletions
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index fd12bc4..9ea104c 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -86,7 +86,7 @@ void ConstraintSatisfaction::Profile(llvm::FoldingSetNodeID &ID, ID.AddPointer(ConstraintOwner); ID.AddInteger(TemplateArgs.size()); for (auto &Arg : TemplateArgs) - Arg.Profile(ID, C); + C.getCanonicalTemplateArgument(Arg).Profile(ID, C); } ConceptReference * diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index e653782..e0b2852 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -226,7 +226,10 @@ UnsignedOrNone Program::createGlobal(const ValueDecl *VD, const Expr *Init) { Globals[PIdx] = NewGlobal; // All pointers pointing to the previous extern decl now point to the // new decl. - RedeclBlock->movePointersTo(NewGlobal->block()); + // A previous iteration might've already fixed up the pointers for this + // global. + if (RedeclBlock != NewGlobal->block()) + RedeclBlock->movePointersTo(NewGlobal->block()); } } PIdx = *Idx; diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 1e376da..75b17c54 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -140,7 +140,8 @@ class ExprPointeeResolve { // explicit cast will be checked in `findPointeeToNonConst` const CastKind kind = ICE->getCastKind(); if (kind == CK_LValueToRValue || kind == CK_DerivedToBase || - kind == CK_UncheckedDerivedToBase) + kind == CK_UncheckedDerivedToBase || + (kind == CK_NoOp && (ICE->getType() == ICE->getSubExpr()->getType()))) return resolveExpr(ICE->getSubExpr()); return false; } @@ -788,13 +789,16 @@ ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) { // FIXME: false positive if the pointee does not change in lambda const auto CaptureNoConst = lambdaExpr(hasCaptureInit(Exp)); - const auto Matches = - match(stmt(anyOf(forEachDescendant( - stmt(anyOf(AssignToNonConst, PassAsNonConstArg, - CastToNonConst, CaptureNoConst)) - .bind("stmt")), - forEachDescendant(InitToNonConst))), - Stm, Context); + const auto ReturnNoConst = + returnStmt(hasReturnValue(canResolveToExprPointee(Exp))); + + const auto Matches = match( + stmt(anyOf(forEachDescendant( + stmt(anyOf(AssignToNonConst, PassAsNonConstArg, + CastToNonConst, CaptureNoConst, ReturnNoConst)) + .bind("stmt")), + forEachDescendant(InitToNonConst))), + Stm, Context); return selectFirst<Stmt>("stmt", Matches); } diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 9261294..b004d73 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -432,7 +432,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, // right-justified. It is used to align compound assignments like `+=` and `=`. // When RightJustify and ACS.PadOperators are true, operators in each block to // be aligned will be padded on the left to the same length before aligning. -template <typename F> +// +// The simple check will not look at the indentaion and nesting level to recurse +// into the line for alignment. It will also not count the commas. This is e.g. +// for aligning macro definitions. +template <typename F, bool SimpleCheck = false> static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt, @@ -465,9 +469,9 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, // Measure the scope level (i.e. depth of (), [], {}) of the first token, and // abort when we hit any token in a higher scope than the starting one. - auto IndentAndNestingLevel = StartAt < Changes.size() - ? Changes[StartAt].indentAndNestingLevel() - : std::tuple<unsigned, unsigned, unsigned>(); + const auto IndentAndNestingLevel = + StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel() + : std::tuple<unsigned, unsigned, unsigned>(); // Keep track of the number of commas before the matching tokens, we will only // align a sequence of matching tokens if they are preceded by the same number @@ -536,14 +540,17 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, if (CurrentChange.Tok->isNot(tok::comment)) LineIsComment = false; - if (CurrentChange.Tok->is(tok::comma)) { - ++CommasBeforeMatch; - } else if (CurrentChange.indentAndNestingLevel() > IndentAndNestingLevel) { - // Call AlignTokens recursively, skipping over this scope block. - unsigned StoppedAt = - AlignTokens(Style, Matches, Changes, i, ACS, RightJustify); - i = StoppedAt - 1; - continue; + if (!SimpleCheck) { + if (CurrentChange.Tok->is(tok::comma)) { + ++CommasBeforeMatch; + } else if (CurrentChange.indentAndNestingLevel() > + IndentAndNestingLevel) { + // Call AlignTokens recursively, skipping over this scope block. + const auto StoppedAt = + AlignTokens(Style, Matches, Changes, i, ACS, RightJustify); + i = StoppedAt - 1; + continue; + } } if (!Matches(CurrentChange)) @@ -656,7 +663,7 @@ void WhitespaceManager::alignConsecutiveMacros() { auto AlignMacrosMatches = [](const Change &C) { const FormatToken *Current = C.Tok; - unsigned SpacesRequiredBefore = 1; + assert(Current); if (Current->SpacesRequiredBefore == 0 || !Current->Previous) return false; @@ -665,79 +672,26 @@ void WhitespaceManager::alignConsecutiveMacros() { // If token is a ")", skip over the parameter list, to the // token that precedes the "(" - if (Current->is(tok::r_paren) && Current->MatchingParen) { - Current = Current->MatchingParen->Previous; - SpacesRequiredBefore = 0; - } - - if (!Current || Current->isNot(tok::identifier)) - return false; - - if (!Current->Previous || Current->Previous->isNot(tok::pp_define)) - return false; - - // For a macro function, 0 spaces are required between the - // identifier and the lparen that opens the parameter list. - // For a simple macro, 1 space is required between the - // identifier and the first token of the defined value. - return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore; - }; - - unsigned MinColumn = 0; - - // Start and end of the token sequence we're processing. - unsigned StartOfSequence = 0; - unsigned EndOfSequence = 0; - - // Whether a matching token has been found on the current line. - bool FoundMatchOnLine = false; - - // Whether the current line consists only of comments - bool LineIsComment = true; - - unsigned I = 0; - for (unsigned E = Changes.size(); I != E; ++I) { - if (Changes[I].NewlinesBefore != 0) { - EndOfSequence = I; - - // Whether to break the alignment sequence because of an empty line. - bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) && - !Style.AlignConsecutiveMacros.AcrossEmptyLines; - - // Whether to break the alignment sequence because of a line without a - // match. - bool NoMatchBreak = - !FoundMatchOnLine && - !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments); - - if (EmptyLineBreak || NoMatchBreak) { - AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn, - AlignMacrosMatches, Changes); + if (Current->is(tok::r_paren)) { + const auto *MatchingParen = Current->MatchingParen; + // For a macro function, 0 spaces are required between the + // identifier and the lparen that opens the parameter list. + if (!MatchingParen || MatchingParen->SpacesRequiredBefore > 0 || + !MatchingParen->Previous) { + return false; } - - // A new line starts, re-initialize line status tracking bools. - FoundMatchOnLine = false; - LineIsComment = true; + Current = MatchingParen->Previous; + } else if (Current->Next->SpacesRequiredBefore != 1) { + // For a simple macro, 1 space is required between the + // identifier and the first token of the defined value. + return false; } - if (Changes[I].Tok->isNot(tok::comment)) - LineIsComment = false; - - if (!AlignMacrosMatches(Changes[I])) - continue; - - FoundMatchOnLine = true; - - if (StartOfSequence == 0) - StartOfSequence = I; - - unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn; - MinColumn = std::max(MinColumn, ChangeMinColumn); - } + return Current->endsSequence(tok::identifier, tok::pp_define); + }; - EndOfSequence = I; - AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn, - AlignMacrosMatches, Changes); + AlignTokens<decltype(AlignMacrosMatches) &, /*SimpleCheck=*/true>( + Style, AlignMacrosMatches, Changes, 0, Style.AlignConsecutiveMacros); } void WhitespaceManager::alignConsecutiveAssignments() { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 829bd87..54cbfe4 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -570,6 +570,11 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments( if (!Constraint.hasParameterMapping()) return std::move(MLTAL); + // The mapping is empty, meaning no template arguments are needed for + // evaluation. + if (Constraint.getParameterMapping().empty()) + return MultiLevelTemplateArgumentList(); + TemplateDeductionInfo Info(Constraint.getBeginLoc()); Sema::InstantiatingTemplate Inst( S, Constraint.getBeginLoc(), @@ -736,8 +741,9 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( UnsubstitutedConstraintSatisfactionCacheResult Cache; Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors; Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied; - std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(), - std::back_inserter(Cache.Satisfaction.Details)); + Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(), + Satisfaction.Details.begin() + Size, + Satisfaction.Details.end()); Cache.SubstExpr = E; S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)}); @@ -868,8 +874,9 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( UnsubstitutedConstraintSatisfactionCacheResult Cache; Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors; Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied; - std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(), - std::back_inserter(Cache.Satisfaction.Details)); + Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(), + Satisfaction.Details.begin() + Size, + Satisfaction.Details.end()); Cache.SubstExpr = E; S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)}); return E; @@ -1012,8 +1019,9 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( UnsubstitutedConstraintSatisfactionCacheResult Cache; Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors; Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied; - std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(), - std::back_inserter(Cache.Satisfaction.Details)); + Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(), + Satisfaction.Details.begin() + Size, + Satisfaction.Details.end()); Cache.SubstExpr = CE; S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)}); return CE; @@ -1217,10 +1225,10 @@ bool Sema::CheckConstraintSatisfaction( return false; } -static const ExprResult -SubstituteConceptsInConstrainExpression(Sema &S, const NamedDecl *D, - const ConceptSpecializationExpr *CSE, - UnsignedOrNone SubstIndex) { +static ExprResult +SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, + const ConceptSpecializationExpr *CSE, + UnsignedOrNone SubstIndex) { // [C++2c] [temp.constr.normal] // Otherwise, to form CE, any non-dependent concept template argument Ai @@ -1255,7 +1263,7 @@ bool Sema::CheckConstraintSatisfaction( const ConceptSpecializationExpr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) { - ExprResult Res = SubstituteConceptsInConstrainExpression( + ExprResult Res = SubstituteConceptsInConstraintExpression( *this, nullptr, ConstraintExpr, ArgPackSubstIndex); if (!Res.isUsable()) return true; @@ -2017,8 +2025,13 @@ void SubstituteParameterMappings::buildParameterMapping( SemaRef.MarkUsedTemplateParameters(Args->arguments(), /*Depth=*/0, OccurringIndices); } + unsigned Size = OccurringIndices.count(); + // When the constraint is independent of any template parameters, + // we build an empty mapping so that we can distinguish these cases + // from cases where no mapping exists at all, e.g. when there are only atomic + // constraints. TemplateArgumentLoc *TempArgs = - new (SemaRef.Context) TemplateArgumentLoc[OccurringIndices.count()]; + new (SemaRef.Context) TemplateArgumentLoc[Size]; llvm::SmallVector<NamedDecl *> UsedParams; for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) { SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I @@ -2039,7 +2052,6 @@ void SubstituteParameterMappings::buildParameterMapping( TemplateParams->getLAngleLoc(), UsedParams, /*RAngleLoc=*/SourceLocation(), /*RequiresClause=*/nullptr); - unsigned Size = OccurringIndices.count(); N.updateParameterMapping( std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption), MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList); @@ -2050,6 +2062,10 @@ bool SubstituteParameterMappings::substitute( if (!N.hasParameterMapping()) buildParameterMapping(N); + // If the parameter mapping is empty, there is nothing to substitute. + if (N.getParameterMapping().empty()) + return false; + SourceLocation InstLocBegin, InstLocEnd; llvm::ArrayRef Arguments = ArgsAsWritten->arguments(); if (Arguments.empty()) { @@ -2289,7 +2305,7 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr( ConceptDecl *CD = CSE->getNamedConcept()->getCanonicalDecl(); ExprResult Res = - SubstituteConceptsInConstrainExpression(S, D, CSE, SubstIndex); + SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex); if (!Res.isUsable()) return nullptr; |