clang  10.0.0svn
SemaConcept.cpp
Go to the documentation of this file.
1 //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements semantic analysis for C++ constraints and concepts.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Sema/Sema.h"
17 #include "clang/Sema/Template.h"
18 #include "clang/AST/ExprCXX.h"
19 using namespace clang;
20 using namespace sema;
21 
22 bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) {
23  // C++2a [temp.constr.atomic]p1
24  // ..E shall be a constant expression of type bool.
25 
26  ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
27 
28  if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
29  if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
30  return CheckConstraintExpression(BinOp->getLHS()) &&
31  CheckConstraintExpression(BinOp->getRHS());
32  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
33  return CheckConstraintExpression(C->getSubExpr());
34 
35  // An atomic constraint!
36  if (ConstraintExpression->isTypeDependent())
37  return true;
38 
39  QualType Type = ConstraintExpression->getType();
40  if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
41  Diag(ConstraintExpression->getExprLoc(),
42  diag::err_non_bool_atomic_constraint) << Type
43  << ConstraintExpression->getSourceRange();
44  return false;
45  }
46  return true;
47 }
48 
49 bool
52  Expr *ConstraintExpr,
53  bool &IsSatisfied) {
54  ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
55 
56  if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
57  if (BO->getOpcode() == BO_LAnd) {
58  if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
59  IsSatisfied))
60  return true;
61  if (!IsSatisfied)
62  return false;
63  return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
64  IsSatisfied);
65  } else if (BO->getOpcode() == BO_LOr) {
66  if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
67  IsSatisfied))
68  return true;
69  if (IsSatisfied)
70  return false;
71  return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
72  IsSatisfied);
73  }
74  }
75  else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
76  return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(),
77  IsSatisfied);
78 
79  EnterExpressionEvaluationContext ConstantEvaluated(
81 
82  // Atomic constraint - substitute arguments and check satisfaction.
83  ExprResult E;
84  {
85  TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc());
86  InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(),
88  NamedConcept, Info,
89  ConstraintExpr->getSourceRange());
90  if (Inst.isInvalid())
91  return true;
92  // We do not want error diagnostics escaping here.
93  Sema::SFINAETrap Trap(*this);
94 
95  E = SubstExpr(ConstraintExpr, MLTAL);
96  if (E.isInvalid() || Trap.hasErrorOccurred()) {
97  // C++2a [temp.constr.atomic]p1
98  // ...If substitution results in an invalid type or expression, the
99  // constraint is not satisfied.
100  IsSatisfied = false;
101  return false;
102  }
103  }
104 
105  if (!CheckConstraintExpression(E.get()))
106  return true;
107 
108  SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
109  Expr::EvalResult EvalResult;
110  EvalResult.Diag = &EvaluationDiags;
111  if (!E.get()->EvaluateAsRValue(EvalResult, Context)) {
112  // C++2a [temp.constr.atomic]p1
113  // ...E shall be a constant expression of type bool.
114  Diag(E.get()->getBeginLoc(),
115  diag::err_non_constant_constraint_expression)
116  << E.get()->getSourceRange();
117  for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
118  Diag(PDiag.first, PDiag.second);
119  return true;
120  }
121 
122  IsSatisfied = EvalResult.Val.getInt().getBoolValue();
123 
124  return false;
125 }
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
A (possibly-)qualified type.
Definition: Type.h:643
Provides information about an attempted template argument deduction, whose success or failure was des...
The base class of the type hierarchy.
Definition: Type.h:1436
RAII object that enters a new expression evaluation context.
Definition: Sema.h:11557
Defines the clang::Expr interface and subclasses for C++ expressions.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:274
bool CheckConstraintExpression(Expr *CE)
Check whether the given expression is a valid constraint expression.
Definition: SemaConcept.cpp:22
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:567
PtrTy get() const
Definition: Ownership.h:170
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:582
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
Definition: Expr.h:176
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:8039
This represents one expression.
Definition: Expr.h:108
QualType getType() const
Definition: Expr.h:137
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition: Template.h:64
bool isInvalid() const
Definition: Ownership.h:166
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:153
A stack object to be created when performing template instantiation.
Definition: Sema.h:7858
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2329
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:221
bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept, MultiLevelTemplateArgumentList &MLTAL, Expr *ConstraintExpr, bool &IsSatisfied)
Definition: SemaConcept.cpp:50
Dataflow Directional Tag Classes.
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:580
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2966
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:262
CanQualType BoolTy
Definition: ASTContext.h:1016
APSInt & getInt()
Definition: APValue.h:380
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:8070