diff options
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r-- | lib/AST/Expr.cpp | 205 |
1 files changed, 137 insertions, 68 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 5f559b7..712de50 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -195,12 +195,12 @@ SourceLocation Expr::getExprLoc() const { case Stmt::NoStmtClass: llvm_unreachable("statement without class"); #define ABSTRACT_STMT(type) #define STMT(type, base) \ - case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break; + case Stmt::type##Class: break; #define EXPR(type, base) \ case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc); #include "clang/AST/StmtNodes.inc" } - llvm_unreachable("unknown statement kind"); + llvm_unreachable("unknown expression kind"); } //===----------------------------------------------------------------------===// @@ -221,11 +221,11 @@ static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D, // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: // - // and + // 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 (T->isDependentType()) { @@ -309,29 +309,11 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) { bool InstantiationDependent = false; computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent, ValueDependent, InstantiationDependent); - - // (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: - if (!TypeDependent && !ValueDependent && - hasExplicitTemplateArgs() && - TemplateSpecializationType::anyDependentTemplateArguments( - getTemplateArgs(), - getNumTemplateArgs(), - InstantiationDependent)) { - TypeDependent = true; - ValueDependent = true; - InstantiationDependent = true; - } - - ExprBits.TypeDependent = TypeDependent; - ExprBits.ValueDependent = ValueDependent; - ExprBits.InstantiationDependent = InstantiationDependent; - + + ExprBits.TypeDependent |= TypeDependent; + ExprBits.ValueDependent |= ValueDependent; + ExprBits.InstantiationDependent |= InstantiationDependent; + // Is the declaration a parameter pack? if (getDecl()->isParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; @@ -340,7 +322,7 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) { DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - ValueDecl *D, bool RefersToEnclosingLocal, + ValueDecl *D, bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -348,14 +330,21 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; - if (QualifierLoc) + if (QualifierLoc) { getInternalQualifierLoc() = QualifierLoc; + auto *NNS = QualifierLoc.getNestedNameSpecifier(); + if (NNS->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (NNS->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + } DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; if (FoundD) getInternalFoundDecl() = FoundD; DeclRefExprBits.HasTemplateKWAndArgsInfo = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; - DeclRefExprBits.RefersToEnclosingLocal = RefersToEnclosingLocal; + DeclRefExprBits.RefersToEnclosingVariableOrCapture = + RefersToEnclosingVariableOrCapture; if (TemplateArgs) { bool Dependent = false; bool InstantiationDependent = false; @@ -364,8 +353,9 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); - if (InstantiationDependent) - setInstantiationDependent(true); + assert(!Dependent && "built a DeclRefExpr with dependent template args"); + ExprBits.InstantiationDependent |= InstantiationDependent; + ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; } else if (TemplateKWLoc.isValid()) { getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } @@ -378,14 +368,14 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingLocal, + bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { return Create(Context, QualifierLoc, TemplateKWLoc, D, - RefersToEnclosingLocal, + RefersToEnclosingVariableOrCapture, DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD, TemplateArgs); } @@ -394,7 +384,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingLocal, + bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, @@ -416,7 +406,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, - RefersToEnclosingLocal, + RefersToEnclosingVariableOrCapture, NameInfo, FoundD, TemplateArgs, T, VK); } @@ -448,6 +438,38 @@ SourceLocation DeclRefExpr::getLocEnd() const { return getNameInfo().getLocEnd(); } +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, + StringLiteral *SL) + : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, + FNTy->isDependentType(), FNTy->isDependentType(), + FNTy->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(L), Type(IT), FnName(SL) {} + +StringLiteral *PredefinedExpr::getFunctionName() { + return cast_or_null<StringLiteral>(FnName); +} + +StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { + switch (IT) { + case Func: + return "__func__"; + case Function: + return "__FUNCTION__"; + case FuncDName: + return "__FUNCDNAME__"; + case LFunction: + return "L__FUNCTION__"; + case PrettyFunction: + return "__PRETTY_FUNCTION__"; + case FuncSig: + return "__FUNCSIG__"; + case PrettyFunctionNoVirtual: + break; + } + llvm_unreachable("Unknown ident type for PredefinedExpr"); +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { @@ -477,6 +499,22 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } return ""; } + if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) { + std::unique_ptr<MangleContext> MC; + MC.reset(Context.createMangleContext()); + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + auto DC = CurrentDecl->getDeclContext(); + if (DC->isFileContext()) + MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out); + else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) + MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); + else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) + MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); + else + MC->mangleBlock(DC, BD, Out); + return Out.str(); + } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) return FD->getNameAsString(); @@ -509,6 +547,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { case CC_X86StdCall: POut << "__stdcall "; break; case CC_X86FastCall: POut << "__fastcall "; break; case CC_X86ThisCall: POut << "__thiscall "; break; + case CC_X86VectorCall: POut << "__vectorcall "; break; // Only bother printing the conventions that MSVC knows about. default: break; } @@ -600,9 +639,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // type deduction and lambdas. For trailing return types resolve the // decltype expression. Otherwise print the real type when this is // not a constructor or destructor. - if ((isa<CXXMethodDecl>(FD) && - cast<CXXMethodDecl>(FD)->getParent()->isLambda()) || - (FT && FT->getReturnType()->getAs<AutoType>())) + if (isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda()) Proto = "auto " + Proto; else if (FT && FT->getReturnType()->getAs<DecltypeType>()) FT->getReturnType() @@ -1252,7 +1290,7 @@ SourceLocation CallExpr::getLocStart() const { return cast<CXXOperatorCallExpr>(this)->getLocStart(); SourceLocation begin = getCallee()->getLocStart(); - if (begin.isInvalid() && getNumArgs() > 0) + if (begin.isInvalid() && getNumArgs() > 0 && getArg(0)) begin = getArg(0)->getLocStart(); return begin; } @@ -1261,7 +1299,7 @@ SourceLocation CallExpr::getLocEnd() const { return cast<CXXOperatorCallExpr>(this)->getLocEnd(); SourceLocation end = getRParenLoc(); - if (end.isInvalid() && getNumArgs() > 0) + if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1)) end = getArg(getNumArgs() - 1)->getLocEnd(); return end; } @@ -2734,10 +2772,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl(); - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + for (const auto *Field : RD->fields()) { // If this is a union, skip all the fields that aren't being initialized. - if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) + if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field) continue; // Don't emit anonymous bitfields, they just affect layout. @@ -2830,9 +2867,16 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, return false; } -bool Expr::HasSideEffects(const ASTContext &Ctx) const { +bool Expr::HasSideEffects(const ASTContext &Ctx, + bool IncludePossibleEffects) const { + // In circumstances where we care about definite side effects instead of + // potential side effects, we want to ignore expressions that are part of a + // macro expansion as a potential side effect. + if (!IncludePossibleEffects && getExprLoc().isMacroID()) + return false; + if (isInstantiationDependent()) - return true; + return IncludePossibleEffects; switch (getStmtClass()) { case NoStmtClass: @@ -2850,6 +2894,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case PackExpansionExprClass: case SubstNonTypeTemplateParmPackExprClass: case FunctionParmPackExprClass: + case TypoExprClass: + case CXXFoldExprClass: llvm_unreachable("shouldn't see dependent / unresolved nodes here"); case DeclRefExprClass: @@ -2883,21 +2929,27 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return false; case CallExprClass: + case CXXOperatorCallExprClass: + case CXXMemberCallExprClass: + case CUDAKernelCallExprClass: + 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; + case MSPropertyRefExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: case StmtExprClass: - case CXXOperatorCallExprClass: - case CXXMemberCallExprClass: - case UserDefinedLiteralClass: case CXXThrowExprClass: case CXXNewExprClass: case CXXDeleteExprClass: case ExprWithCleanupsClass: - case CXXBindTemporaryExprClass: - case BlockExprClass: - case CUDAKernelCallExprClass: // These always have a side-effect. return true; @@ -2933,25 +2985,29 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case InitListExprClass: // FIXME: The children for an InitListExpr doesn't include the array filler. if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller()) - if (E->HasSideEffects(Ctx)) + if (E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; break; case GenericSelectionExprClass: return cast<GenericSelectionExpr>(this)->getResultExpr()-> - HasSideEffects(Ctx); + HasSideEffects(Ctx, IncludePossibleEffects); case ChooseExprClass: - return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx); + return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); case CXXDefaultArgExprClass: - return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx); + return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects( + Ctx, IncludePossibleEffects); - case CXXDefaultInitExprClass: - if (const Expr *E = cast<CXXDefaultInitExpr>(this)->getExpr()) - return E->HasSideEffects(Ctx); + case CXXDefaultInitExprClass: { + const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField(); + if (const Expr *E = FD->getInClassInitializer()) + return E->HasSideEffects(Ctx, IncludePossibleEffects); // If we've not yet parsed the initializer, assume it has side-effects. return true; + } case CXXDynamicCastExprClass: { // A dynamic_cast expression has side-effects if it can throw. @@ -2966,6 +3022,13 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case CXXReinterpretCastExprClass: case CXXConstCastExprClass: case CXXFunctionalCastExprClass: { + // While volatile reads are side-effecting in both C and C++, we treat them + // as having possible (not definite) side-effects. This allows idiomatic + // code to behave without warning, such as sizeof(*v) for a volatile- + // qualified pointer. + if (!IncludePossibleEffects) + break; + const CastExpr *CE = cast<CastExpr>(this); if (CE->getCastKind() == CK_LValueToRValue && CE->getSubExpr()->getType().isVolatileQualified()) @@ -2981,7 +3044,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case CXXConstructExprClass: case CXXTemporaryObjectExprClass: { const CXXConstructExpr *CE = cast<CXXConstructExpr>(this); - if (!CE->getConstructor()->isTrivial()) + if (!CE->getConstructor()->isTrivial() && IncludePossibleEffects) return true; // A trivial constructor does not add any side-effects of its own. Just look // at its arguments. @@ -3009,7 +3072,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { const Expr *Subexpr = *I; if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Subexpr)) Subexpr = OVE->getSourceExpr(); - if (Subexpr->HasSideEffects(Ctx)) + if (Subexpr->HasSideEffects(Ctx, IncludePossibleEffects)) return true; } return false; @@ -3018,22 +3081,24 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case ObjCBoxedExprClass: case ObjCArrayLiteralClass: case ObjCDictionaryLiteralClass: - case ObjCMessageExprClass: case ObjCSelectorExprClass: case ObjCProtocolExprClass: - case ObjCPropertyRefExprClass: case ObjCIsaExprClass: case ObjCIndirectCopyRestoreExprClass: case ObjCSubscriptRefExprClass: case ObjCBridgedCastExprClass: - // FIXME: Classify these cases better. - return true; + case ObjCMessageExprClass: + case ObjCPropertyRefExprClass: + // FIXME: Classify these cases better. + if (IncludePossibleEffects) + return true; + break; } // Recurse to children. for (const_child_range SubStmts = children(); SubStmts; ++SubStmts) if (const Stmt *S = *SubStmts) - if (cast<Expr>(S)->HasSideEffects(Ctx)) + if (cast<Expr>(S)->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; @@ -3279,6 +3344,10 @@ FieldDecl *Expr::getSourceBitField() { return BinOp->getRHS()->getSourceBitField(); } + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) + if (UnOp->isPrefix() && UnOp->isIncrementDecrementOp()) + return UnOp->getSubExpr()->getSourceBitField(); + return nullptr; } @@ -3759,7 +3828,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, // Compute type- and value-dependence. Expr *Index = IndexExprs[IndexIdx]; if (Index->isTypeDependent() || Index->isValueDependent()) - ExprBits.ValueDependent = true; + ExprBits.TypeDependent = ExprBits.ValueDependent = true; if (Index->isInstantiationDependent()) ExprBits.InstantiationDependent = true; // Propagate unexpanded parameter packs. @@ -3774,7 +3843,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, Expr *End = IndexExprs[IndexIdx + 1]; if (Start->isTypeDependent() || Start->isValueDependent() || End->isTypeDependent() || End->isValueDependent()) { - ExprBits.ValueDependent = true; + ExprBits.TypeDependent = ExprBits.ValueDependent = true; ExprBits.InstantiationDependent = true; } else if (Start->isInstantiationDependent() || End->isInstantiationDependent()) { |