diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 125 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 69 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 36 |
6 files changed, 26 insertions, 257 deletions
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 89c3f6c47b4..742343583d1 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -32,7 +32,6 @@ add_clang_library(clangSema SemaCast.cpp SemaChecking.cpp SemaCodeComplete.cpp - SemaConcept.cpp SemaConsumer.cpp SemaCoroutine.cpp SemaCUDA.cpp diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp deleted file mode 100644 index 3131609390a..00000000000 --- a/clang/lib/Sema/SemaConcept.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for C++ constraints and concepts. -// -//===----------------------------------------------------------------------===// - -#include "clang/Sema/Sema.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "clang/Sema/TemplateDeduction.h" -#include "clang/Sema/Template.h" -#include "clang/AST/ExprCXX.h" -using namespace clang; -using namespace sema; - -bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) { - // C++2a [temp.constr.atomic]p1 - // ..E shall be a constant expression of type bool. - - ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); - - if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) { - if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr) - return CheckConstraintExpression(BinOp->getLHS()) && - CheckConstraintExpression(BinOp->getRHS()); - } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) - return CheckConstraintExpression(C->getSubExpr()); - - // An atomic constraint! - if (ConstraintExpression->isTypeDependent()) - return true; - - QualType Type = ConstraintExpression->getType(); - if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { - Diag(ConstraintExpression->getExprLoc(), - diag::err_non_bool_atomic_constraint) << Type - << ConstraintExpression->getSourceRange(); - return false; - } - return true; -} - -bool -Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept, - MultiLevelTemplateArgumentList &MLTAL, - Expr *ConstraintExpr, - bool &IsSatisfied) { - ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); - - if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) { - if (BO->getOpcode() == BO_LAnd) { - if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(), - IsSatisfied)) - return true; - if (!IsSatisfied) - return false; - return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(), - IsSatisfied); - } else if (BO->getOpcode() == BO_LOr) { - if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(), - IsSatisfied)) - return true; - if (IsSatisfied) - return false; - return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(), - IsSatisfied); - } - } - else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) - return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(), - IsSatisfied); - - EnterExpressionEvaluationContext ConstantEvaluated( - *this, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - // Atomic constraint - substitute arguments and check satisfaction. - ExprResult E; - { - TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc()); - InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(), - InstantiatingTemplate::ConstraintSubstitution{}, - NamedConcept, Info, - ConstraintExpr->getSourceRange()); - if (Inst.isInvalid()) - return true; - // We do not want error diagnostics escaping here. - Sema::SFINAETrap Trap(*this); - - E = SubstExpr(ConstraintExpr, MLTAL); - if (E.isInvalid() || Trap.hasErrorOccurred()) { - // C++2a [temp.constr.atomic]p1 - // ...If substitution results in an invalid type or expression, the - // constraint is not satisfied. - IsSatisfied = false; - return false; - } - } - - if (!CheckConstraintExpression(E.get())) - return true; - - SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; - Expr::EvalResult EvalResult; - EvalResult.Diag = &EvaluationDiags; - if (!E.get()->EvaluateAsRValue(EvalResult, Context)) { - // C++2a [temp.constr.atomic]p1 - // ...E shall be a constant expression of type bool. - Diag(E.get()->getBeginLoc(), - diag::err_non_constant_constraint_expression) - << E.get()->getSourceRange(); - for (const PartialDiagnosticAt &PDiag : EvaluationDiags) - Diag(PDiag.first, PDiag.second); - return true; - } - - IsSatisfied = EvalResult.Val.getInt().getBoolValue(); - - return false; -} diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 76fd10d2e63..0f3a27233ee 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1314,7 +1314,6 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::SizeOfPackExprClass: case Expr::StringLiteralClass: case Expr::SourceLocExprClass: - case Expr::ConceptSpecializationExprClass: // These expressions can never throw. return CT_Cannot; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index cb756eb30f6..284962f3e07 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4271,47 +4271,14 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name, ExprResult Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - SourceLocation ConceptNameLoc, - NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, + const DeclarationNameInfo &NameInfo, + ConceptDecl *Template, + SourceLocation TemplateLoc, const TemplateArgumentListInfo *TemplateArgs) { - assert(NamedConcept && "A concept template id without a template?"); - - llvm::SmallVector<TemplateArgument, 4> Converted; - if (CheckTemplateArgumentList(NamedConcept, ConceptNameLoc, - const_cast<TemplateArgumentListInfo&>(*TemplateArgs), - /*PartialTemplateArgs=*/false, Converted, - /*UpdateArgsWithConversion=*/false)) - return ExprError(); - - Optional<bool> IsSatisfied; - bool AreArgsDependent = false; - for (TemplateArgument &Arg : Converted) { - if (Arg.isDependent()) { - AreArgsDependent = true; - break; - } - } - if (!AreArgsDependent) { - InstantiatingTemplate Inst(*this, ConceptNameLoc, - InstantiatingTemplate::ConstraintsCheck{}, NamedConcept, Converted, - SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameLoc, - TemplateArgs->getRAngleLoc())); - MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Converted); - bool Satisfied; - if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, - NamedConcept->getConstraintExpr(), - Satisfied)) - return ExprError(); - IsSatisfied = Satisfied; - } - return ConceptSpecializationExpr::Create(Context, - SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, - TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept, - ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), Converted, - IsSatisfied); + // TODO: Do concept specialization here. + Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) << + "concept specialization"; + return ExprError(); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, @@ -4355,10 +4322,9 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, } if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) { - return CheckConceptTemplateId(SS, TemplateKWLoc, - R.getLookupNameInfo().getBeginLoc(), - R.getFoundDecl(), - R.getAsSingle<ConceptDecl>(), TemplateArgs); + return CheckConceptTemplateId(SS, R.getLookupNameInfo(), + R.getAsSingle<ConceptDecl>(), + TemplateKWLoc, TemplateArgs); } // We don't want lookup warnings at this point. @@ -8088,7 +8054,20 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, TemplateParameterLists.front(), ConstraintExpr); - + + if (!ConstraintExpr->isTypeDependent() && + ConstraintExpr->getType() != Context.BoolTy) { + // C++2a [temp.constr.atomic]p3: + // E shall be a constant expression of type bool. + // TODO: Do this check for individual atomic constraints + // and not the constraint expression. Probably should do it in + // ParseConstraintExpression. + Diag(ConstraintExpr->getSourceRange().getBegin(), + diag::err_concept_initialized_with_non_bool_type) + << ConstraintExpr->getType(); + NewDecl->setInvalidDecl(); + } + if (NewDecl->getAssociatedConstraints()) { // C++2a [temp.concept]p4: // A concept shall not have associated constraints. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 42411c9c33f..9091bc5b80d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -198,14 +198,12 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const { case ExplicitTemplateArgumentSubstitution: case DeducedTemplateArgumentSubstitution: case PriorTemplateArgumentSubstitution: - case ConstraintsCheck: return true; case DefaultTemplateArgumentChecking: case DeclaringSpecialMember: case DefiningSynthesizedFunction: case ExceptionSpecEvaluation: - case ConstraintSubstitution: return false; // This function should never be called when Kind's value is Memoization. @@ -360,24 +358,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( PointOfInstantiation, InstantiationRange, Param, Template, TemplateArgs) {} -Sema::InstantiatingTemplate::InstantiatingTemplate( - Sema &SemaRef, SourceLocation PointOfInstantiation, - ConstraintsCheck, TemplateDecl *Template, - ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange) - : InstantiatingTemplate( - SemaRef, CodeSynthesisContext::ConstraintsCheck, - PointOfInstantiation, InstantiationRange, Template, nullptr, - TemplateArgs) {} - -Sema::InstantiatingTemplate::InstantiatingTemplate( - Sema &SemaRef, SourceLocation PointOfInstantiation, - ConstraintSubstitution, TemplateDecl *Template, - sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) - : InstantiatingTemplate( - SemaRef, CodeSynthesisContext::ConstraintSubstitution, - PointOfInstantiation, InstantiationRange, Template, nullptr, - {}, &DeductionInfo) {} - void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) { Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext; InNonInstantiationSFINAEContext = false; @@ -684,30 +664,6 @@ void Sema::PrintInstantiationStack() { case CodeSynthesisContext::Memoization: break; - - case CodeSynthesisContext::ConstraintsCheck: - if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) { - SmallVector<char, 128> TemplateArgsStr; - llvm::raw_svector_ostream OS(TemplateArgsStr); - CD->printName(OS); - printTemplateArgumentList(OS, Active->template_arguments(), - getPrintingPolicy()); - Diags.Report(Active->PointOfInstantiation, - diag::note_concept_specialization_here) - << OS.str() - << Active->InstantiationRange; - break; - } - // TODO: Concepts - implement this for constrained templates and partial - // specializations. - llvm_unreachable("only concept constraints are supported right now"); - break; - - case CodeSynthesisContext::ConstraintSubstitution: - Diags.Report(Active->PointOfInstantiation, - diag::note_constraint_substitution_here) - << Active->InstantiationRange; - break; } } } @@ -731,7 +687,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { LLVM_FALLTHROUGH; case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: case CodeSynthesisContext::ExceptionSpecInstantiation: - case CodeSynthesisContext::ConstraintsCheck: // This is a template instantiation, so there is no SFINAE. return None; @@ -745,10 +700,8 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: - case CodeSynthesisContext::ConstraintSubstitution: - // We're either substituting explicitly-specified template arguments - // or deduced template arguments or a constraint expression, so SFINAE - // applies. + // We're either substitution explicitly-specified template arguments + // or deduced template arguments, so SFINAE applies. assert(Active->DeductionInfo && "Missing deduction info pointer"); return Active->DeductionInfo; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8184d4c09b4..59cac787876 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3019,25 +3019,6 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildConceptSpecializationExpr(NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - TemplateArgumentListInfo *TALI) { - CXXScopeSpec SS; - SS.Adopt(NNS); - ExprResult Result = getSema().CheckConceptTemplateId(SS, TemplateKWLoc, - ConceptNameLoc, - FoundDecl, - NamedConcept, TALI); - if (Result.isInvalid()) - return ExprError(); - return Result; - } - - /// \brief Build a new Objective-C boxed expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { return getSema().BuildObjCBoxedExpr(SR, ValueExpr); } @@ -11035,23 +11016,6 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { template<typename Derived> ExprResult -TreeTransform<Derived>::TransformConceptSpecializationExpr( - ConceptSpecializationExpr *E) { - const ASTTemplateArgumentListInfo *Old = E->getTemplateArgsAsWritten(); - TemplateArgumentListInfo TransArgs(Old->LAngleLoc, Old->RAngleLoc); - if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(), - Old->NumTemplateArgs, TransArgs)) - return ExprError(); - - return getDerived().RebuildConceptSpecializationExpr( - E->getNestedNameSpecifierLoc(), E->getTemplateKWLoc(), - E->getConceptNameLoc(), E->getFoundDecl(), E->getNamedConcept(), - &TransArgs); -} - - -template<typename Derived> -ExprResult TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); if (!T) |