2020-03-17 15:33:37 +08:00
|
|
|
//===- ComputeDependence.cpp ----------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/ComputeDependence.h"
|
|
|
|
#include "clang/AST/Attr.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclarationName.h"
|
|
|
|
#include "clang/AST/DependenceFlags.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
#include "clang/AST/ExprConcepts.h"
|
|
|
|
#include "clang/AST/ExprObjC.h"
|
|
|
|
#include "clang/AST/ExprOpenMP.h"
|
|
|
|
#include "clang/Basic/ExceptionSpecificationType.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(FullExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(OpaqueValueExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
if (auto *S = E->getSourceExpr())
|
|
|
|
D |= S->getDependence();
|
|
|
|
assert(!(D & ExprDependence::UnexpandedPack));
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ParenExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(UnaryOperator *E) {
|
|
|
|
return toExprDependence(E->getType()->getDependence()) |
|
|
|
|
E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) {
|
|
|
|
// Never type-dependent (C++ [temp.dep.expr]p3).
|
|
|
|
// Value-dependent if the argument is type-dependent.
|
|
|
|
if (E->isArgumentType())
|
|
|
|
return turnTypeToValueDependence(
|
|
|
|
toExprDependence(E->getArgumentType()->getDependence()));
|
|
|
|
|
|
|
|
auto ArgDeps = E->getArgumentExpr()->getDependence();
|
|
|
|
auto Deps = ArgDeps & ~ExprDependence::TypeValue;
|
|
|
|
// Value-dependent if the argument is type-dependent.
|
|
|
|
if (ArgDeps & ExprDependence::Type)
|
|
|
|
Deps |= ExprDependence::Value;
|
|
|
|
// Check to see if we are in the situation where alignof(decl) should be
|
|
|
|
// dependent because decl's alignment is dependent.
|
|
|
|
auto ExprKind = E->getKind();
|
|
|
|
if (ExprKind != UETT_AlignOf && ExprKind != UETT_PreferredAlignOf)
|
|
|
|
return Deps;
|
|
|
|
if ((Deps & ExprDependence::Value) && (Deps & ExprDependence::Instantiation))
|
|
|
|
return Deps;
|
|
|
|
|
|
|
|
auto *NoParens = E->getArgumentExpr()->IgnoreParens();
|
|
|
|
const ValueDecl *D = nullptr;
|
|
|
|
if (const auto *DRE = dyn_cast<DeclRefExpr>(NoParens))
|
|
|
|
D = DRE->getDecl();
|
|
|
|
else if (const auto *ME = dyn_cast<MemberExpr>(NoParens))
|
|
|
|
D = ME->getMemberDecl();
|
|
|
|
if (!D)
|
|
|
|
return Deps;
|
|
|
|
for (const auto *I : D->specific_attrs<AlignedAttr>()) {
|
2020-04-13 05:06:00 +08:00
|
|
|
if (I->isAlignmentErrorDependent())
|
|
|
|
Deps |= ExprDependence::Error;
|
2020-03-17 15:33:37 +08:00
|
|
|
if (I->isAlignmentDependent())
|
2020-04-13 05:06:00 +08:00
|
|
|
Deps |= ExprDependence::ValueInstantiation;
|
2020-03-17 15:33:37 +08:00
|
|
|
}
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ArraySubscriptExpr *E) {
|
|
|
|
return E->getLHS()->getDependence() | E->getRHS()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CompoundLiteralExpr *E) {
|
|
|
|
return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()) |
|
|
|
|
turnTypeToValueDependence(E->getInitializer()->getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CastExpr *E) {
|
|
|
|
// Cast expressions are type-dependent if the type is
|
|
|
|
// dependent (C++ [temp.dep.expr]p3).
|
|
|
|
// Cast expressions are value-dependent if the type is
|
|
|
|
// dependent or if the subexpression is value-dependent.
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
if (E->getStmtClass() == Stmt::ImplicitCastExprClass) {
|
|
|
|
// An implicit cast expression doesn't (lexically) contain an
|
|
|
|
// unexpanded pack, even if its target type does.
|
|
|
|
D &= ~ExprDependence::UnexpandedPack;
|
|
|
|
}
|
|
|
|
if (auto *S = E->getSubExpr())
|
|
|
|
D |= S->getDependence() & ~ExprDependence::Type;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(BinaryOperator *E) {
|
|
|
|
return E->getLHS()->getDependence() | E->getRHS()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ConditionalOperator *E) {
|
|
|
|
// The type of the conditional operator depends on the type of the conditional
|
|
|
|
// to support the GCC vector conditional extension. Additionally,
|
|
|
|
// [temp.dep.expr] does specify state that this should be dependent on ALL sub
|
|
|
|
// expressions.
|
|
|
|
return E->getCond()->getDependence() | E->getLHS()->getDependence() |
|
|
|
|
E->getRHS()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
|
|
|
|
return E->getCommon()->getDependence() | E->getFalseExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
|
2020-03-17 17:36:19 +08:00
|
|
|
// FIXME: why is unexpanded-pack not propagated?
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence()) &
|
|
|
|
~ExprDependence::UnexpandedPack;
|
2020-03-17 15:33:37 +08:00
|
|
|
// Note: we treat a statement-expression in a dependent context as always
|
|
|
|
// being value- and instantiation-dependent. This matches the behavior of
|
|
|
|
// lambda-expressions and GCC.
|
|
|
|
if (TemplateDepth)
|
|
|
|
D |= ExprDependence::ValueInstantiation;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ConvertVectorExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence()) |
|
|
|
|
E->getSrcExpr()->getDependence();
|
|
|
|
if (!E->getType()->isDependentType())
|
|
|
|
D &= ~ExprDependence::Type;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ChooseExpr *E) {
|
|
|
|
if (E->isConditionDependent())
|
|
|
|
return ExprDependence::TypeValueInstantiation |
|
|
|
|
E->getCond()->getDependence() | E->getLHS()->getDependence() |
|
|
|
|
E->getRHS()->getDependence();
|
|
|
|
|
|
|
|
auto Cond = E->getCond()->getDependence();
|
|
|
|
auto Active = E->getLHS()->getDependence();
|
|
|
|
auto Inactive = E->getRHS()->getDependence();
|
|
|
|
if (!E->isConditionTrue())
|
|
|
|
std::swap(Active, Inactive);
|
|
|
|
// Take type- and value- dependency from the active branch. Propagate all
|
|
|
|
// other flags from all branches.
|
|
|
|
return (Active & ExprDependence::TypeValue) |
|
|
|
|
((Cond | Active | Inactive) & ~ExprDependence::TypeValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ParenListExpr *P) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
for (auto *E : P->exprs())
|
|
|
|
D |= E->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(VAArgExpr *E) {
|
|
|
|
auto D =
|
|
|
|
toExprDependence(E->getWrittenTypeInfo()->getType()->getDependence()) |
|
|
|
|
(E->getSubExpr()->getDependence() & ~ExprDependence::Type);
|
|
|
|
return D & ~ExprDependence::Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(NoInitExpr *E) {
|
|
|
|
return toExprDependence(E->getType()->getDependence()) &
|
2020-03-28 01:53:23 +08:00
|
|
|
(ExprDependence::Instantiation | ExprDependence::Error);
|
2020-03-17 15:33:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
|
|
|
|
auto D = E->getCommonExpr()->getDependence() |
|
|
|
|
E->getSubExpr()->getDependence() | ExprDependence::Instantiation;
|
|
|
|
if (!E->getType()->isInstantiationDependentType())
|
|
|
|
D &= ~ExprDependence::Instantiation;
|
|
|
|
return turnTypeToValueDependence(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ImplicitValueInitExpr *E) {
|
|
|
|
return toExprDependence(E->getType()->getDependence()) &
|
|
|
|
ExprDependence::Instantiation;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ExtVectorElementExpr *E) {
|
|
|
|
return E->getBase()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(BlockExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
if (E->getBlockDecl()->isDependentContext())
|
|
|
|
D |= ExprDependence::Instantiation;
|
|
|
|
return D & ~ExprDependence::UnexpandedPack;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(AsTypeExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence()) |
|
|
|
|
E->getSrcExpr()->getDependence();
|
|
|
|
if (!E->getType()->isDependentType())
|
|
|
|
D &= ~ExprDependence::Type;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
|
|
|
|
return E->getSemanticForm()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
|
|
|
|
auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
|
2020-03-17 17:36:19 +08:00
|
|
|
D |= toExprDependence(E->getType()->getDependence()) &
|
|
|
|
(ExprDependence::Type | ExprDependence::Error);
|
2020-03-17 15:33:37 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXTypeidExpr *E) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
if (E->isTypeOperand())
|
|
|
|
D = toExprDependence(
|
|
|
|
E->getTypeOperandSourceInfo()->getType()->getDependence());
|
|
|
|
else
|
|
|
|
D = turnTypeToValueDependence(E->getExprOperand()->getDependence());
|
|
|
|
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
|
|
|
|
return D & ~ExprDependence::Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(MSPropertyRefExpr *E) {
|
|
|
|
return E->getBaseExpr()->getDependence() & ~ExprDependence::Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(MSPropertySubscriptExpr *E) {
|
|
|
|
return E->getIdx()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXUuidofExpr *E) {
|
|
|
|
if (E->isTypeOperand())
|
|
|
|
return turnTypeToValueDependence(toExprDependence(
|
|
|
|
E->getTypeOperandSourceInfo()->getType()->getDependence()));
|
|
|
|
|
|
|
|
return turnTypeToValueDependence(E->getExprOperand()->getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXThisExpr *E) {
|
|
|
|
// 'this' is type-dependent if the class type of the enclosing
|
|
|
|
// member function is dependent (C++ [temp.dep.expr]p2)
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
assert(!(D & ExprDependence::UnexpandedPack));
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXThrowExpr *E) {
|
|
|
|
auto *Op = E->getSubExpr();
|
|
|
|
if (!Op)
|
|
|
|
return ExprDependence::None;
|
|
|
|
return Op->getDependence() & ~ExprDependence::TypeValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXBindTemporaryExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXScalarValueInitExpr *E) {
|
|
|
|
return toExprDependence(E->getType()->getDependence()) &
|
|
|
|
~ExprDependence::TypeValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXDeleteExpr *E) {
|
|
|
|
return turnTypeToValueDependence(E->getArgument()->getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ArrayTypeTraitExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getQueriedType()->getDependence());
|
|
|
|
if (auto *Dim = E->getDimensionExpression())
|
|
|
|
D |= Dim->getDependence();
|
|
|
|
return turnTypeToValueDependence(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ExpressionTraitExpr *E) {
|
|
|
|
// Never type-dependent.
|
|
|
|
auto D = E->getQueriedExpression()->getDependence() & ~ExprDependence::Type;
|
|
|
|
// Value-dependent if the argument is type-dependent.
|
|
|
|
if (E->getQueriedExpression()->isTypeDependent())
|
|
|
|
D |= ExprDependence::Value;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXNoexceptExpr *E, CanThrowResult CT) {
|
|
|
|
auto D = E->getOperand()->getDependence() & ~ExprDependence::TypeValue;
|
|
|
|
if (CT == CT_Dependent)
|
|
|
|
D |= ExprDependence::ValueInstantiation;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2020-03-17 17:36:19 +08:00
|
|
|
ExprDependence clang::computeDependence(PackExpansionExpr *E) {
|
|
|
|
return (E->getPattern()->getDependence() & ~ExprDependence::UnexpandedPack) |
|
|
|
|
ExprDependence::TypeValueInstantiation;
|
|
|
|
}
|
|
|
|
|
2020-03-17 15:33:37 +08:00
|
|
|
ExprDependence clang::computeDependence(SubstNonTypeTemplateParmExpr *E) {
|
|
|
|
return E->getReplacement()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CoroutineSuspendExpr *E) {
|
|
|
|
if (auto *Resume = E->getResumeExpr())
|
2020-03-17 17:36:19 +08:00
|
|
|
return (Resume->getDependence() &
|
|
|
|
(ExprDependence::TypeValue | ExprDependence::Error)) |
|
2020-03-17 15:33:37 +08:00
|
|
|
(E->getCommonExpr()->getDependence() & ~ExprDependence::TypeValue);
|
|
|
|
return E->getCommonExpr()->getDependence() |
|
|
|
|
ExprDependence::TypeValueInstantiation;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(DependentCoawaitExpr *E) {
|
|
|
|
return E->getOperand()->getDependence() |
|
|
|
|
ExprDependence::TypeValueInstantiation;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCBoxedExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCEncodeExpr *E) {
|
|
|
|
return toExprDependence(E->getEncodedType()->getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCIvarRefExpr *E) {
|
|
|
|
return turnTypeToValueDependence(E->getBase()->getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCPropertyRefExpr *E) {
|
|
|
|
if (E->isObjectReceiver())
|
|
|
|
return E->getBase()->getDependence() & ~ExprDependence::Type;
|
|
|
|
if (E->isSuperReceiver())
|
|
|
|
return toExprDependence(E->getSuperReceiverType()->getDependence()) &
|
|
|
|
~ExprDependence::TypeValue;
|
|
|
|
assert(E->isClassReceiver());
|
|
|
|
return ExprDependence::None;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCSubscriptRefExpr *E) {
|
|
|
|
return E->getBaseExpr()->getDependence() | E->getKeyExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCIsaExpr *E) {
|
|
|
|
return E->getBase()->getDependence() & ~ExprDependence::Type &
|
|
|
|
~ExprDependence::UnexpandedPack;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCIndirectCopyRestoreExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
|
|
|
|
auto D = E->getBase()->getDependence();
|
|
|
|
if (auto *LB = E->getLowerBound())
|
|
|
|
D |= LB->getDependence();
|
|
|
|
if (auto *Len = E->getLength())
|
|
|
|
D |= Len->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
[OPENMP50]Add basic support for array-shaping operation.
Summary:
Added basic representation and parsing/sema handling of array-shaping
operations. Array shaping expression is an expression of form ([s0]..[sn])base,
where s0, ..., sn must be a positive integer, base - a pointer. This
expression is a kind of cast operation that converts pointer expression
into an array-like kind of expression.
Reviewers: rjmccall, rsmith, jdoerfert
Subscribers: guansong, arphaman, cfe-commits, caomhin, kkwli0
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74144
2020-02-05 22:33:05 +08:00
|
|
|
ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
|
|
|
|
auto D = E->getBase()->getDependence() |
|
|
|
|
toExprDependence(E->getType()->getDependence());
|
|
|
|
for (Expr *Dim: E->getDimensions())
|
|
|
|
if (Dim)
|
|
|
|
D |= Dim->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2020-04-02 03:06:38 +08:00
|
|
|
ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
|
|
|
|
if (auto *VD = cast_or_null<ValueDecl>(E->getIteratorDecl(I)))
|
|
|
|
D |= toExprDependence(VD->getType()->getDependence());
|
|
|
|
OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I);
|
|
|
|
if (Expr *BE = IR.Begin)
|
|
|
|
D |= BE->getDependence();
|
|
|
|
if (Expr *EE = IR.End)
|
|
|
|
D |= EE->getDependence();
|
|
|
|
if (Expr *SE = IR.Step)
|
|
|
|
D |= SE->getDependence();
|
|
|
|
}
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2020-03-17 15:33:37 +08:00
|
|
|
/// Compute the type-, value-, and instantiation-dependence of a
|
|
|
|
/// declaration reference
|
|
|
|
/// based on the declaration being referenced.
|
|
|
|
ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
|
|
|
|
auto Deps = ExprDependence::None;
|
|
|
|
|
|
|
|
if (auto *NNS = E->getQualifier())
|
2020-03-28 01:51:25 +08:00
|
|
|
Deps |= toExprDependence(NNS->getDependence() &
|
|
|
|
~NestedNameSpecifierDependence::Dependent);
|
2020-03-17 15:33:37 +08:00
|
|
|
|
|
|
|
if (auto *FirstArg = E->getTemplateArgs()) {
|
|
|
|
unsigned NumArgs = E->getNumTemplateArgs();
|
|
|
|
for (auto *Arg = FirstArg, *End = FirstArg + NumArgs; Arg < End; ++Arg)
|
|
|
|
Deps |= toExprDependence(Arg->getArgument().getDependence());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto *Decl = E->getDecl();
|
|
|
|
auto Type = E->getType();
|
|
|
|
|
|
|
|
if (Decl->isParameterPack())
|
|
|
|
Deps |= ExprDependence::UnexpandedPack;
|
2020-03-17 17:36:19 +08:00
|
|
|
Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
|
2020-03-17 15:33:37 +08:00
|
|
|
|
|
|
|
// (TD) C++ [temp.dep.expr]p3:
|
|
|
|
// An id-expression is type-dependent if it contains:
|
|
|
|
//
|
|
|
|
// and
|
|
|
|
//
|
|
|
|
// (VD) C++ [temp.dep.constexpr]p2:
|
|
|
|
// An identifier is value-dependent if it is:
|
|
|
|
|
|
|
|
// (TD) - an identifier that was declared with dependent type
|
|
|
|
// (VD) - a name declared with a dependent type,
|
|
|
|
if (Type->isDependentType())
|
|
|
|
return Deps | ExprDependence::TypeValueInstantiation;
|
|
|
|
else if (Type->isInstantiationDependentType())
|
|
|
|
Deps |= ExprDependence::Instantiation;
|
|
|
|
|
|
|
|
// (TD) - a conversion-function-id that specifies a dependent type
|
|
|
|
if (Decl->getDeclName().getNameKind() ==
|
|
|
|
DeclarationName::CXXConversionFunctionName) {
|
|
|
|
QualType T = Decl->getDeclName().getCXXNameType();
|
|
|
|
if (T->isDependentType())
|
|
|
|
return Deps | ExprDependence::TypeValueInstantiation;
|
|
|
|
|
|
|
|
if (T->isInstantiationDependentType())
|
|
|
|
Deps |= ExprDependence::Instantiation;
|
|
|
|
}
|
|
|
|
|
|
|
|
// (VD) - the name of a non-type template parameter,
|
|
|
|
if (isa<NonTypeTemplateParmDecl>(Decl))
|
|
|
|
return Deps | ExprDependence::ValueInstantiation;
|
|
|
|
|
|
|
|
// (VD) - a constant with integral or enumeration type and is
|
|
|
|
// initialized with an expression that is value-dependent.
|
|
|
|
// (VD) - a constant with literal type and is initialized with an
|
|
|
|
// expression that is value-dependent [C++11].
|
|
|
|
// (VD) - FIXME: Missing from the standard:
|
|
|
|
// - an entity with reference type and is initialized with an
|
|
|
|
// expression that is value-dependent [C++11]
|
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
|
|
|
|
if ((Ctx.getLangOpts().CPlusPlus11
|
|
|
|
? Var->getType()->isLiteralType(Ctx)
|
|
|
|
: Var->getType()->isIntegralOrEnumerationType()) &&
|
|
|
|
(Var->getType().isConstQualified() ||
|
|
|
|
Var->getType()->isReferenceType())) {
|
|
|
|
if (const Expr *Init = Var->getAnyInitializer())
|
|
|
|
if (Init->isValueDependent()) {
|
|
|
|
Deps |= ExprDependence::ValueInstantiation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// (VD) - FIXME: Missing from the standard:
|
|
|
|
// - a member function or a static data member of the current
|
|
|
|
// instantiation
|
|
|
|
if (Var->isStaticDataMember() &&
|
|
|
|
Var->getDeclContext()->isDependentContext()) {
|
|
|
|
Deps |= ExprDependence::ValueInstantiation;
|
|
|
|
TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo();
|
|
|
|
if (TInfo->getType()->isIncompleteArrayType())
|
|
|
|
Deps |= ExprDependence::Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
// (VD) - FIXME: Missing from the standard:
|
|
|
|
// - a member function or a static data member of the current
|
|
|
|
// instantiation
|
|
|
|
if (isa<CXXMethodDecl>(Decl) && Decl->getDeclContext()->isDependentContext())
|
|
|
|
Deps |= ExprDependence::ValueInstantiation;
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
ExprDependence clang::computeDependence(RecoveryExpr *E) {
|
|
|
|
// FIXME: drop type+value+instantiation once Error is sufficient to suppress
|
|
|
|
// bogus dianostics.
|
|
|
|
auto D = ExprDependence::TypeValueInstantiation | ExprDependence::Error;
|
|
|
|
for (auto *S : E->subExpressions())
|
|
|
|
D |= S->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2020-03-17 15:33:37 +08:00
|
|
|
ExprDependence clang::computeDependence(PredefinedExpr *E) {
|
|
|
|
return toExprDependence(E->getType()->getDependence()) &
|
|
|
|
~ExprDependence::UnexpandedPack;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CallExpr *E,
|
|
|
|
llvm::ArrayRef<Expr *> PreArgs) {
|
|
|
|
auto D = E->getCallee()->getDependence();
|
|
|
|
for (auto *A : llvm::makeArrayRef(E->getArgs(), E->getNumArgs())) {
|
|
|
|
if (A)
|
|
|
|
D |= A->getDependence();
|
|
|
|
}
|
|
|
|
for (auto *A : PreArgs)
|
|
|
|
D |= A->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(OffsetOfExpr *E) {
|
|
|
|
auto D = turnTypeToValueDependence(
|
|
|
|
toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()));
|
|
|
|
for (unsigned I = 0, N = E->getNumExpressions(); I < N; ++I)
|
|
|
|
D |= turnTypeToValueDependence(E->getIndexExpr(I)->getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(MemberExpr *E) {
|
2020-03-19 06:38:08 +08:00
|
|
|
auto *MemberDecl = E->getMemberDecl();
|
|
|
|
auto D = E->getBase()->getDependence();
|
|
|
|
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
|
|
|
|
DeclContext *DC = MemberDecl->getDeclContext();
|
|
|
|
// dyn_cast_or_null is used to handle objC variables which do not
|
|
|
|
// have a declaration context.
|
|
|
|
CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
|
|
|
|
if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) {
|
|
|
|
if (!E->getType()->isDependentType())
|
|
|
|
D &= ~ExprDependence::Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bitfield with value-dependent width is type-dependent.
|
|
|
|
if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent()) {
|
|
|
|
D |= ExprDependence::Type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME: move remaining dependence computation from MemberExpr::Create()
|
|
|
|
return D;
|
2020-03-17 15:33:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(InitListExpr *E) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
for (auto *A : E->inits())
|
|
|
|
D |= A->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ShuffleVectorExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
for (auto *C : llvm::makeArrayRef(E->getSubExprs(), E->getNumSubExprs()))
|
|
|
|
D |= C->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(GenericSelectionExpr *E,
|
|
|
|
bool ContainsUnexpandedPack) {
|
|
|
|
auto D = ContainsUnexpandedPack ? ExprDependence::UnexpandedPack
|
|
|
|
: ExprDependence::None;
|
2020-03-17 17:36:19 +08:00
|
|
|
for (auto *AE : E->getAssocExprs())
|
|
|
|
D |= AE->getDependence() & ExprDependence::Error;
|
|
|
|
D |= E->getControllingExpr()->getDependence() & ExprDependence::Error;
|
|
|
|
|
2020-03-17 15:33:37 +08:00
|
|
|
if (E->isResultDependent())
|
|
|
|
return D | ExprDependence::TypeValueInstantiation;
|
|
|
|
return D | (E->getResultExpr()->getDependence() &
|
|
|
|
~ExprDependence::UnexpandedPack);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(DesignatedInitExpr *E) {
|
|
|
|
auto Deps = E->getInit()->getDependence();
|
|
|
|
for (auto D : E->designators()) {
|
|
|
|
auto DesignatorDeps = ExprDependence::None;
|
|
|
|
if (D.isArrayDesignator())
|
|
|
|
DesignatorDeps |= E->getArrayIndex(D)->getDependence();
|
|
|
|
else if (D.isArrayRangeDesignator())
|
|
|
|
DesignatorDeps |= E->getArrayRangeStart(D)->getDependence() |
|
|
|
|
E->getArrayRangeEnd(D)->getDependence();
|
|
|
|
Deps |= DesignatorDeps;
|
|
|
|
if (DesignatorDeps & ExprDependence::TypeValue)
|
|
|
|
Deps |= ExprDependence::TypeValueInstantiation;
|
|
|
|
}
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(PseudoObjectExpr *O) {
|
|
|
|
auto D = O->getSyntacticForm()->getDependence();
|
|
|
|
for (auto *E : O->semantics())
|
|
|
|
D |= E->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(AtomicExpr *A) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
for (auto *E : llvm::makeArrayRef(A->getSubExprs(), A->getNumSubExprs()))
|
|
|
|
D |= E->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXNewExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
auto Size = E->getArraySize();
|
|
|
|
if (Size.hasValue() && *Size)
|
|
|
|
D |= turnTypeToValueDependence((*Size)->getDependence());
|
|
|
|
if (auto *I = E->getInitializer())
|
|
|
|
D |= turnTypeToValueDependence(I->getDependence());
|
|
|
|
for (auto *A : E->placement_arguments())
|
|
|
|
D |= turnTypeToValueDependence(A->getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
|
|
|
|
auto D = E->getBase()->getDependence();
|
|
|
|
if (!E->getDestroyedType().isNull())
|
|
|
|
D |= toExprDependence(E->getDestroyedType()->getDependence());
|
|
|
|
if (auto *ST = E->getScopeTypeInfo())
|
|
|
|
D |= turnTypeToValueDependence(
|
|
|
|
toExprDependence(ST->getType()->getDependence()));
|
|
|
|
if (auto *Q = E->getQualifier())
|
2020-03-28 01:51:25 +08:00
|
|
|
D |= toExprDependence(Q->getDependence() &
|
|
|
|
~NestedNameSpecifierDependence::Dependent);
|
2020-03-17 15:33:37 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
if (Name.isInstantiationDependent())
|
|
|
|
D |= ExprDependence::Instantiation;
|
|
|
|
if (Name.containsUnexpandedParameterPack())
|
|
|
|
D |= ExprDependence::UnexpandedPack;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence
|
|
|
|
clang::computeDependence(OverloadExpr *E, bool KnownDependent,
|
|
|
|
bool KnownInstantiationDependent,
|
|
|
|
bool KnownContainsUnexpandedParameterPack) {
|
|
|
|
auto Deps = ExprDependence::None;
|
|
|
|
if (KnownDependent)
|
|
|
|
Deps |= ExprDependence::TypeValue;
|
|
|
|
if (KnownInstantiationDependent)
|
|
|
|
Deps |= ExprDependence::Instantiation;
|
|
|
|
if (KnownContainsUnexpandedParameterPack)
|
|
|
|
Deps |= ExprDependence::UnexpandedPack;
|
|
|
|
Deps |= getDependenceInExpr(E->getNameInfo());
|
|
|
|
if (auto *Q = E->getQualifier())
|
2020-03-28 01:51:25 +08:00
|
|
|
Deps |= toExprDependence(Q->getDependence() &
|
|
|
|
~NestedNameSpecifierDependence::Dependent);
|
2020-03-17 15:33:37 +08:00
|
|
|
for (auto *D : E->decls()) {
|
|
|
|
if (D->getDeclContext()->isDependentContext() ||
|
|
|
|
isa<UnresolvedUsingValueDecl>(D))
|
|
|
|
Deps |= ExprDependence::TypeValueInstantiation;
|
|
|
|
}
|
|
|
|
// If we have explicit template arguments, check for dependent
|
|
|
|
// template arguments and whether they contain any unexpanded pack
|
|
|
|
// expansions.
|
|
|
|
for (auto A : E->template_arguments())
|
|
|
|
Deps |= toExprDependence(A.getArgument().getDependence());
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) {
|
|
|
|
auto D = ExprDependence::TypeValue;
|
|
|
|
D |= getDependenceInExpr(E->getNameInfo());
|
|
|
|
if (auto *Q = E->getQualifier())
|
|
|
|
D |= toExprDependence(Q->getDependence());
|
|
|
|
for (auto A : E->template_arguments())
|
|
|
|
D |= toExprDependence(A.getArgument().getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXConstructExpr *E) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
2020-03-17 16:48:35 +08:00
|
|
|
for (auto *A : E->arguments())
|
|
|
|
D |= A->getDependence() & ~ExprDependence::Type;
|
2020-03-17 15:33:37 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(LambdaExpr *E,
|
|
|
|
bool ContainsUnexpandedParameterPack) {
|
|
|
|
auto D = toExprDependence(E->getType()->getDependence());
|
|
|
|
if (ContainsUnexpandedParameterPack)
|
|
|
|
D |= ExprDependence::UnexpandedPack;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
|
|
|
|
auto D = ExprDependence::ValueInstantiation;
|
|
|
|
D |= toExprDependence(E->getType()->getDependence());
|
|
|
|
if (E->getType()->getContainedDeducedType())
|
|
|
|
D |= ExprDependence::Type;
|
|
|
|
for (auto *A : E->arguments())
|
2020-03-17 17:36:19 +08:00
|
|
|
D |= A->getDependence() &
|
|
|
|
(ExprDependence::UnexpandedPack | ExprDependence::Error);
|
2020-03-17 15:33:37 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(CXXDependentScopeMemberExpr *E) {
|
|
|
|
auto D = ExprDependence::TypeValueInstantiation;
|
|
|
|
if (!E->isImplicitAccess())
|
|
|
|
D |= E->getBase()->getDependence();
|
|
|
|
if (auto *Q = E->getQualifier())
|
|
|
|
D |= toExprDependence(Q->getDependence());
|
|
|
|
D |= getDependenceInExpr(E->getMemberNameInfo());
|
|
|
|
for (auto A : E->template_arguments())
|
|
|
|
D |= toExprDependence(A.getArgument().getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(MaterializeTemporaryExpr *E) {
|
|
|
|
return E->getSubExpr()->getDependence();
|
|
|
|
}
|
|
|
|
|
2020-03-17 17:36:19 +08:00
|
|
|
ExprDependence clang::computeDependence(CXXFoldExpr *E) {
|
|
|
|
auto D = ExprDependence::TypeValueInstantiation;
|
|
|
|
for (const auto *C : {E->getLHS(), E->getRHS()}) {
|
|
|
|
if (C)
|
|
|
|
D |= C->getDependence() & ~ExprDependence::UnexpandedPack;
|
|
|
|
}
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
2020-03-17 15:33:37 +08:00
|
|
|
ExprDependence clang::computeDependence(TypeTraitExpr *E) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
for (const auto *A : E->getArgs())
|
|
|
|
D |=
|
|
|
|
toExprDependence(A->getType()->getDependence()) & ~ExprDependence::Type;
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ConceptSpecializationExpr *E,
|
|
|
|
bool ValueDependent) {
|
|
|
|
auto TA = TemplateArgumentDependence::None;
|
|
|
|
const auto InterestingDeps = TemplateArgumentDependence::Instantiation |
|
|
|
|
TemplateArgumentDependence::UnexpandedPack;
|
|
|
|
for (const TemplateArgumentLoc &ArgLoc :
|
|
|
|
E->getTemplateArgsAsWritten()->arguments()) {
|
|
|
|
TA |= ArgLoc.getArgument().getDependence() & InterestingDeps;
|
|
|
|
if (TA == InterestingDeps)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence D =
|
|
|
|
ValueDependent ? ExprDependence::Value : ExprDependence::None;
|
|
|
|
return D | toExprDependence(TA);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCArrayLiteral *E) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
Expr **Elements = E->getElements();
|
|
|
|
for (unsigned I = 0, N = E->getNumElements(); I != N; ++I)
|
|
|
|
D |= turnTypeToValueDependence(Elements[I]->getDependence());
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCDictionaryLiteral *E) {
|
|
|
|
auto Deps = ExprDependence::None;
|
|
|
|
for (unsigned I = 0, N = E->getNumElements(); I < N; ++I) {
|
|
|
|
auto KV = E->getKeyValueElement(I);
|
|
|
|
auto KVDeps = turnTypeToValueDependence(KV.Key->getDependence() |
|
|
|
|
KV.Value->getDependence());
|
|
|
|
if (KV.EllipsisLoc.isValid())
|
|
|
|
KVDeps &= ~ExprDependence::UnexpandedPack;
|
|
|
|
Deps |= KVDeps;
|
|
|
|
}
|
|
|
|
return Deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprDependence clang::computeDependence(ObjCMessageExpr *E) {
|
|
|
|
auto D = ExprDependence::None;
|
|
|
|
if (auto *R = E->getInstanceReceiver())
|
|
|
|
D |= R->getDependence();
|
|
|
|
else
|
|
|
|
D |= toExprDependence(E->getType()->getDependence());
|
|
|
|
for (auto *A : E->arguments())
|
|
|
|
D |= A->getDependence();
|
|
|
|
return D;
|
|
|
|
}
|