diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Sema/CheckExprLifetime.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAPINotes.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenACC.cpp | 169 |
6 files changed, 24 insertions, 179 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index e9ca8ce..9abaf79 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -29,7 +29,7 @@ #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" #include "clang/Analysis/Analyses/CalledOnceCheck.h" #include "clang/Analysis/Analyses/Consumed.h" -#include "clang/Analysis/Analyses/LifetimeSafety.h" +#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h" #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/Analysis/Analyses/ThreadSafety.h" #include "clang/Analysis/Analyses/UninitializedValues.h" diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 51e0ee1..0ebf56e 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -111,6 +111,7 @@ add_clang_library(clangSema clangAPINotes clangAST clangAnalysis + clangAnalysisLifetimeSafety clangBasic clangEdit clangLex diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index e8a7ad3..8aebf53 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -10,7 +10,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/Analysis/Analyses/LifetimeAnnotations.h" +#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Sema.h" diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 35cdfbf..0d8d0fa 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -17,7 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/TypeLoc.h" -#include "clang/Analysis/Analyses/LifetimeAnnotations.h" +#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Sema/SemaObjC.h" diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index f4df63c..9cbd1bd 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -604,6 +604,10 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments( return std::nullopt; const NormalizedConstraint::OccurenceList &Used = Constraint.mappingOccurenceList(); + // The empty MLTAL situation should only occur when evaluating non-dependent + // constraints. + if (!MLTAL.getNumSubstitutedLevels()) + MLTAL.addOuterTemplateArguments(TD, {}, /*Final=*/false); SubstitutedOuterMost = llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost()); unsigned Offset = 0; @@ -623,9 +627,7 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments( if (Offset < SubstitutedOuterMost.size()) SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset); - MLTAL.replaceOutermostTemplateArguments( - const_cast<NamedDecl *>(Constraint.getConstraintDecl()), - SubstitutedOuterMost); + MLTAL.replaceOutermostTemplateArguments(TD, SubstitutedOuterMost); return std::move(MLTAL); } @@ -956,11 +958,20 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( ? Constraint.getPackSubstitutionIndex() : PackSubstitutionIndex; - Sema::InstantiatingTemplate _(S, ConceptId->getBeginLoc(), - Sema::InstantiatingTemplate::ConstraintsCheck{}, - ConceptId->getNamedConcept(), - MLTAL.getInnermost(), - Constraint.getSourceRange()); + Sema::InstantiatingTemplate InstTemplate( + S, ConceptId->getBeginLoc(), + Sema::InstantiatingTemplate::ConstraintsCheck{}, + ConceptId->getNamedConcept(), + // We may have empty template arguments when checking non-dependent + // nested constraint expressions. + // In such cases, non-SFINAE errors would have already been diagnosed + // during parameter mapping substitution, so the instantiating template + // arguments are less useful here. + MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost() + : ArrayRef<TemplateArgument>{}, + Constraint.getSourceRange()); + if (InstTemplate.isInvalid()) + return ExprError(); unsigned Size = Satisfaction.Details.size(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 779b6e9..f3969a9 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -2898,15 +2898,6 @@ OpenACCReductionRecipe SemaOpenACC::CreateReductionInitRecipe( dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts())) VarTy = ASE->getElementType(); - llvm::SmallVector<OpenACCReductionRecipe::CombinerRecipe, 1> CombinerRecipes; - - // We use the 'set-ness' of the alloca-decl to determine whether the combiner - // is 'set' or not, so we can skip any attempts at it if we're going to fail - // at any of the combiners. - if (CreateReductionCombinerRecipe(VarExpr->getBeginLoc(), ReductionOperator, - VarTy, CombinerRecipes)) - return OpenACCReductionRecipe::Empty(); - VarDecl *AllocaDecl = CreateAllocaDecl( getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(), &getASTContext().Idents.get("openacc.reduction.init"), VarTy); @@ -2955,163 +2946,5 @@ OpenACCReductionRecipe SemaOpenACC::CreateReductionInitRecipe( AllocaDecl->setInit(Init.get()); AllocaDecl->setInitStyle(VarDecl::CallInit); } - - return OpenACCReductionRecipe(AllocaDecl, CombinerRecipes); -} - -bool SemaOpenACC::CreateReductionCombinerRecipe( - SourceLocation Loc, OpenACCReductionOperator ReductionOperator, - QualType VarTy, - llvm::SmallVectorImpl<OpenACCReductionRecipe::CombinerRecipe> - &CombinerRecipes) { - // Now we can try to generate the 'combiner' recipe. This is a little - // complicated in that if the 'VarTy' is an array type, we want to take its - // element type so we can generate that. Additionally, if this is a struct, - // we have two options: If there is overloaded operators, we want to take - // THOSE, else we want to do the individual elements. - - BinaryOperatorKind BinOp; - switch (ReductionOperator) { - case OpenACCReductionOperator::Invalid: - // This can only happen when there is an error, and since these inits - // are used for code generation, we can just ignore/not bother doing any - // initialization here. - CombinerRecipes.push_back({nullptr, nullptr, nullptr}); - return false; - case OpenACCReductionOperator::Addition: - BinOp = BinaryOperatorKind::BO_AddAssign; - break; - case OpenACCReductionOperator::Multiplication: - BinOp = BinaryOperatorKind::BO_MulAssign; - break; - case OpenACCReductionOperator::BitwiseAnd: - BinOp = BinaryOperatorKind::BO_AndAssign; - break; - case OpenACCReductionOperator::BitwiseOr: - BinOp = BinaryOperatorKind::BO_OrAssign; - break; - case OpenACCReductionOperator::BitwiseXOr: - BinOp = BinaryOperatorKind::BO_XorAssign; - break; - - case OpenACCReductionOperator::Max: - case OpenACCReductionOperator::Min: - case OpenACCReductionOperator::And: - case OpenACCReductionOperator::Or: - // We just want a 'NYI' error in the backend, so leave an empty combiner - // recipe, and claim success. - CombinerRecipes.push_back({nullptr, nullptr, nullptr}); - return false; - } - - // If VarTy is an array type, at the top level only, we want to do our - // compares/decomp/etc at the element level. - if (auto *AT = getASTContext().getAsArrayType(VarTy)) - VarTy = AT->getElementType(); - - assert(!VarTy->isArrayType() && "Only 1 level of array allowed"); - - auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE, - bool IncludeTrap) { - // TODO: OpenACC: we have to figure out based on the bin-op how to do the - // ones that we can't just use compound operators for. So &&, ||, max, and - // min aren't really clear what we could do here. - if (IncludeTrap) { - // Trap all of the errors here, we'll emit our own at the end. - Sema::TentativeAnalysisScope Trap{SemaRef}; - - return SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, - RHSDRE, - /*ForFoldExpr=*/false); - } else { - return SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, - RHSDRE, - /*ForFoldExpr=*/false); - } - }; - - struct CombinerAttemptTy { - VarDecl *LHS; - DeclRefExpr *LHSDRE; - VarDecl *RHS; - DeclRefExpr *RHSDRE; - Expr *Op; - }; - - auto formCombiner = [&, this](QualType Ty) -> CombinerAttemptTy { - VarDecl *LHSDecl = CreateAllocaDecl( - getASTContext(), SemaRef.getCurContext(), Loc, - &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty); - auto *LHSDRE = DeclRefExpr::Create( - getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, LHSDecl, - /*ReferstoEnclosingVariableOrCapture=*/false, - DeclarationNameInfo{DeclarationName{LHSDecl->getDeclName()}, - LHSDecl->getBeginLoc()}, - Ty, clang::VK_LValue, LHSDecl, nullptr, NOUR_None); - VarDecl *RHSDecl = CreateAllocaDecl( - getASTContext(), SemaRef.getCurContext(), Loc, - &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty); - auto *RHSDRE = DeclRefExpr::Create( - getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, RHSDecl, - /*ReferstoEnclosingVariableOrCapture=*/false, - DeclarationNameInfo{DeclarationName{RHSDecl->getDeclName()}, - RHSDecl->getBeginLoc()}, - Ty, clang::VK_LValue, RHSDecl, nullptr, NOUR_None); - - ExprResult BinOpResult = tryCombiner(LHSDRE, RHSDRE, /*IncludeTrap=*/true); - - return {LHSDecl, LHSDRE, RHSDecl, RHSDRE, BinOpResult.get()}; - }; - - CombinerAttemptTy TopLevelCombinerInfo = formCombiner(VarTy); - - if (TopLevelCombinerInfo.Op) { - if (!TopLevelCombinerInfo.Op->containsErrors() && - TopLevelCombinerInfo.Op->isInstantiationDependent()) { - // If this is instantiation dependent, we're just going to 'give up' here - // and count on us to get it right during instantaition. - CombinerRecipes.push_back({nullptr, nullptr, nullptr}); - return false; - } else if (!TopLevelCombinerInfo.Op->containsErrors()) { - // Else, we succeeded, we can just return this combiner. - CombinerRecipes.push_back({TopLevelCombinerInfo.LHS, - TopLevelCombinerInfo.RHS, - TopLevelCombinerInfo.Op}); - return false; - } - } - - // Since the 'root' level didn't fail, the only thing that could be successful - // is a struct that we decompose on its individual fields. - - RecordDecl *RD = VarTy->getAsRecordDecl(); - if (!RD) { - Diag(Loc, diag::err_acc_reduction_recipe_no_op) << VarTy; - tryCombiner(TopLevelCombinerInfo.LHSDRE, TopLevelCombinerInfo.RHSDRE, - /*IncludeTrap=*/false); - return true; - } - - for (const FieldDecl *FD : RD->fields()) { - CombinerAttemptTy FieldCombinerInfo = formCombiner(FD->getType()); - - if (!FieldCombinerInfo.Op || FieldCombinerInfo.Op->containsErrors()) { - Diag(Loc, diag::err_acc_reduction_recipe_no_op) << FD->getType(); - Diag(FD->getBeginLoc(), diag::note_acc_reduction_recipe_noop_field) << RD; - tryCombiner(FieldCombinerInfo.LHSDRE, FieldCombinerInfo.RHSDRE, - /*IncludeTrap=*/false); - return true; - } - - if (FieldCombinerInfo.Op->isInstantiationDependent()) { - // If this is instantiation dependent, we're just going to 'give up' here - // and count on us to get it right during instantaition. - CombinerRecipes.push_back({nullptr, nullptr, nullptr}); - } else { - CombinerRecipes.push_back( - {FieldCombinerInfo.LHS, FieldCombinerInfo.RHS, FieldCombinerInfo.Op}); - } - } - - return false; + return OpenACCReductionRecipe(AllocaDecl, {}); } |