diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/Expr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/Expr.cpp | 140 |
1 files changed, 81 insertions, 59 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 712de50..76a4da2 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -1141,40 +1141,13 @@ CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, RParenLoc = rparenloc; } -CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, +CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : Expr(CallExprClass, t, VK, OK_Ordinary, - fn->isTypeDependent(), - fn->isValueDependent(), - fn->isInstantiationDependent(), - fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { - - SubExprs = new (C) Stmt*[args.size()+PREARGS_START]; - SubExprs[FN] = fn; - for (unsigned i = 0; i != args.size(); ++i) { - if (args[i]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (args[i]->isValueDependent()) - ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - SubExprs[i+PREARGS_START] = args[i]; - } - - CallExprBits.NumPreArgs = 0; - RParenLoc = rparenloc; + : CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) { } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { - // FIXME: Why do we allocate this? - SubExprs = new (C) Stmt*[PREARGS_START]; - CallExprBits.NumPreArgs = 0; -} + : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {} CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) @@ -1271,16 +1244,21 @@ bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const { return false; } -QualType CallExpr::getCallReturnType() const { - QualType CalleeType = getCallee()->getType(); - if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>()) +QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { + const Expr *Callee = getCallee(); + QualType CalleeType = Callee->getType(); + if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) { CalleeType = FnTypePtr->getPointeeType(); - else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) + } else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) { CalleeType = BPT->getPointeeType(); - else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) + } else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) { + if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens())) + return Ctx.VoidTy; + // This should never be overloaded and so should never return null. - CalleeType = Expr::findBoundMemberType(getCallee()); - + CalleeType = Expr::findBoundMemberType(Callee); + } + const FunctionType *FnType = CalleeType->castAs<FunctionType>(); return FnType->getReturnType(); } @@ -1360,16 +1338,50 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask); } -MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - ValueDecl *memberdecl, - DeclAccessPair founddecl, - DeclarationNameInfo nameinfo, - const TemplateArgumentListInfo *targs, - QualType ty, - ExprValueKind vk, - ExprObjectKind ok) { +UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType, + SourceLocation op, SourceLocation rp) + : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + E->isTypeDependent(), E->isInstantiationDependent(), + E->containsUnexpandedParameterPack()), + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = false; + Argument.Ex = E; + + // Check to see if we are in the situation where alignof(decl) should be + // dependent because decl's alignment is dependent. + if (ExprKind == UETT_AlignOf) { + if (!isValueDependent() || !isInstantiationDependent()) { + E = E->IgnoreParens(); + + const ValueDecl *D = nullptr; + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + D = DRE->getDecl(); + else if (const auto *ME = dyn_cast<MemberExpr>(E)) + D = ME->getMemberDecl(); + + if (D) { + for (const auto *I : D->specific_attrs<AlignedAttr>()) { + if (I->isAlignmentDependent()) { + setValueDependent(true); + setInstantiationDependent(true); + break; + } + } + } + } + } +} + +MemberExpr *MemberExpr::Create( + const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + ValueDecl *memberdecl, DeclAccessPair founddecl, + DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, + QualType ty, ExprValueKind vk, ExprObjectKind ok) { std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (QualifierLoc || @@ -1384,8 +1396,8 @@ MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow, Size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); - MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, - ty, vk, ok); + MemberExpr *E = new (Mem) + MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok); if (hasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. @@ -2132,8 +2144,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case OO_Greater: case OO_GreaterEqual: case OO_LessEqual: - if (Op->getCallReturnType()->isReferenceType() || - Op->getCallReturnType()->isVoidType()) + if (Op->getCallReturnType(Ctx)->isReferenceType() || + Op->getCallReturnType(Ctx)->isVoidType()) break; WarnE = this; Loc = Op->getOperatorLoc(); @@ -2149,12 +2161,16 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { + const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); + bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr() + : FD->hasAttr<WarnUnusedResultAttr>(); + // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. // // Note: If new cases are added here, DiagnoseUnusedExprResult should be // updated to match for QoI. - if (FD->hasAttr<WarnUnusedResultAttr>() || + if (HasWarnUnusedResultAttr || FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) { WarnE = this; Loc = CE->getCallee()->getLocStart(); @@ -2200,9 +2216,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } if (const ObjCMethodDecl *MD = ME->getMethodDecl()) - if (MD->hasAttr<WarnUnusedResultAttr>() || - (MD->isPropertyAccessor() && !MD->getReturnType()->isVoidType() && - !ME->getReceiverType()->isObjCIdType())) { + if (MD->hasAttr<WarnUnusedResultAttr>()) { WarnE = this; Loc = getExprLoc(); return true; @@ -2387,7 +2401,7 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return type; } - assert(isa<UnresolvedMemberExpr>(expr)); + assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr)); return QualType(); } @@ -2932,11 +2946,19 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXOperatorCallExprClass: case CXXMemberCallExprClass: case CUDAKernelCallExprClass: + case UserDefinedLiteralClass: { + // We don't know a call definitely has side effects, except for calls + // to pure/const functions that definitely don't. + // If the call itself is considered side-effect free, check the operands. + const Decl *FD = cast<CallExpr>(this)->getCalleeDecl(); + bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>()); + if (IsPure || !IncludePossibleEffects) + break; + return true; + } + case BlockExprClass: case CXXBindTemporaryExprClass: - case UserDefinedLiteralClass: - // We don't know a call definitely has side effects, but we can check the - // call's operands. if (!IncludePossibleEffects) break; return true; |