summaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ExprConstant.cpp84
-rw-r--r--lib/AST/MicrosoftMangle.cpp18
2 files changed, 87 insertions, 15 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 6dcb705c44d3..fe77c7f6f3bf 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -4543,6 +4543,12 @@ public:
Call.getLValueBase().dyn_cast<const ValueDecl*>());
if (!FD)
return Error(Callee);
+ // Don't call function pointers which have been cast to some other type.
+ // Per DR (no number yet), the caller and callee can differ in noexcept.
+ if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec(
+ CalleeType->getPointeeType(), FD->getType())) {
+ return Error(E);
+ }
// Overloaded operator calls to member functions are represented as normal
// calls with '*this' as the first argument.
@@ -4558,14 +4564,42 @@ public:
return false;
This = &ThisVal;
Args = Args.slice(1);
+ } else if (MD && MD->isLambdaStaticInvoker()) {
+ // Map the static invoker for the lambda back to the call operator.
+ // Conveniently, we don't have to slice out the 'this' argument (as is
+ // being done for the non-static case), since a static member function
+ // doesn't have an implicit argument passed in.
+ const CXXRecordDecl *ClosureClass = MD->getParent();
+ assert(
+ ClosureClass->captures_begin() == ClosureClass->captures_end() &&
+ "Number of captures must be zero for conversion to function-ptr");
+
+ const CXXMethodDecl *LambdaCallOp =
+ ClosureClass->getLambdaCallOperator();
+
+ // Set 'FD', the function that will be called below, to the call
+ // operator. If the closure object represents a generic lambda, find
+ // the corresponding specialization of the call operator.
+
+ if (ClosureClass->isGenericLambda()) {
+ assert(MD->isFunctionTemplateSpecialization() &&
+ "A generic lambda's static-invoker function must be a "
+ "template specialization");
+ const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
+ FunctionTemplateDecl *CallOpTemplate =
+ LambdaCallOp->getDescribedFunctionTemplate();
+ void *InsertPos = nullptr;
+ FunctionDecl *CorrespondingCallOpSpecialization =
+ CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
+ assert(CorrespondingCallOpSpecialization &&
+ "We must always have a function call operator specialization "
+ "that corresponds to our static invoker specialization");
+ FD = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
+ } else
+ FD = LambdaCallOp;
}
- // Don't call function pointers which have been cast to some other type.
- // Per DR (no number yet), the caller and callee can differ in noexcept.
- if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec(
- CalleeType->getPointeeType(), FD->getType())) {
- return Error(E);
- }
+
} else
return Error(E);
@@ -5834,6 +5868,7 @@ namespace {
bool VisitCXXConstructExpr(const CXXConstructExpr *E) {
return VisitCXXConstructExpr(E, E->getType());
}
+ bool VisitLambdaExpr(const LambdaExpr *E);
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
@@ -6168,6 +6203,21 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
return true;
}
+bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) {
+ const CXXRecordDecl *ClosureClass = E->getLambdaClass();
+ if (ClosureClass->isInvalidDecl()) return false;
+
+ if (Info.checkingPotentialConstantExpression()) return true;
+ if (E->capture_size()) {
+ Info.FFDiag(E, diag::note_unimplemented_constexpr_lambda_feature_ast)
+ << "can not evaluate lambda expressions with captures";
+ return false;
+ }
+ // FIXME: Implement captures.
+ Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0);
+ return true;
+}
+
static bool EvaluateRecord(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isRecordType() &&
@@ -6217,6 +6267,9 @@ public:
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) {
return VisitConstructExpr(E);
}
+ bool VisitLambdaExpr(const LambdaExpr *E) {
+ return VisitConstructExpr(E);
+ }
};
} // end anonymous namespace
@@ -10357,10 +10410,25 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
const FunctionDecl *Callee,
- ArrayRef<const Expr*> Args) const {
+ ArrayRef<const Expr*> Args,
+ const Expr *This) const {
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated);
+ LValue ThisVal;
+ const LValue *ThisPtr = nullptr;
+ if (This) {
+#ifndef NDEBUG
+ auto *MD = dyn_cast<CXXMethodDecl>(Callee);
+ assert(MD && "Don't provide `this` for non-methods.");
+ assert(!MD->isStatic() && "Don't provide `this` for static methods.");
+#endif
+ if (EvaluateObjectArgument(Info, This, ThisVal))
+ ThisPtr = &ThisVal;
+ if (Info.EvalStatus.HasSideEffects)
+ return false;
+ }
+
ArgVector ArgValues(Args.size());
for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
I != E; ++I) {
@@ -10373,7 +10441,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
}
// Build fake call to Callee.
- CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr,
+ CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr,
ArgValues.data());
return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects;
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 911b8b471a05..76c368d7f04c 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -109,13 +109,13 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
static const FunctionDecl *getStructor(const NamedDecl *ND) {
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
- return FTD->getTemplatedDecl();
+ return FTD->getTemplatedDecl()->getCanonicalDecl();
const auto *FD = cast<FunctionDecl>(ND);
if (const auto *FTD = FD->getPrimaryTemplate())
- return FTD->getTemplatedDecl();
+ return FTD->getTemplatedDecl()->getCanonicalDecl();
- return FD;
+ return FD->getCanonicalDecl();
}
/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
@@ -312,6 +312,10 @@ public:
void mangleNestedName(const NamedDecl *ND);
private:
+ bool isStructorDecl(const NamedDecl *ND) const {
+ return ND == Structor || getStructor(ND) == Structor;
+ }
+
void mangleUnqualifiedName(const NamedDecl *ND) {
mangleUnqualifiedName(ND, ND->getDeclName());
}
@@ -898,7 +902,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
llvm_unreachable("Can't mangle Objective-C selector names here!");
case DeclarationName::CXXConstructorName:
- if (Structor == getStructor(ND)) {
+ if (isStructorDecl(ND)) {
if (StructorType == Ctor_CopyingClosure) {
Out << "?_O";
return;
@@ -912,7 +916,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
return;
case DeclarationName::CXXDestructorName:
- if (ND == Structor)
+ if (isStructorDecl(ND))
// If the named decl is the C++ destructor we're mangling,
// use the type we were given.
mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
@@ -1862,7 +1866,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
IsStructor = true;
IsCtorClosure = (StructorType == Ctor_CopyingClosure ||
StructorType == Ctor_DefaultClosure) &&
- getStructor(MD) == Structor;
+ isStructorDecl(MD);
if (IsCtorClosure)
CC = getASTContext().getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true);
@@ -1883,7 +1887,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// <return-type> ::= <type>
// ::= @ # structors (they have no declared return type)
if (IsStructor) {
- if (isa<CXXDestructorDecl>(D) && D == Structor &&
+ if (isa<CXXDestructorDecl>(D) && isStructorDecl(D) &&
StructorType == Dtor_Deleting) {
// The scalar deleting destructor takes an extra int argument.
// However, the FunctionType generated has 0 arguments.