static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef<Expr *> CallArgs) { QualType Ty = Callback->getType(); DeclRefExpr *Call = M.makeDeclRefExpr(Callback); Expr *SubExpr; if (Ty->isRValueReferenceType()) { SubExpr = M.makeImplicitCast( Call, Ty.getNonReferenceType(), CK_LValueToRValue); } else if (Ty->isLValueReferenceType() && Call->getType()->isFunctionType()) { Ty = C.getPointerType(Ty.getNonReferenceType()); SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay); } else if (Ty->isLValueReferenceType() && Call->getType()->isPointerType() && Call->getType()->getPointeeType()->isFunctionType()){ SubExpr = Call; } else { llvm_unreachable("Unexpected state"); } return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation()); }
/// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType using the pre-computed implicit /// conversion sequence ICS. Returns true if there was an error, false /// otherwise. The expression From is replaced with the converted /// expression. Flavor is the kind of conversion we're performing, /// used in the error message. bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence &ICS, const char* Flavor) { switch (ICS.ConversionKind) { case ImplicitConversionSequence::StandardConversion: if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor)) return true; break; case ImplicitConversionSequence::UserDefinedConversion: // FIXME: This is, of course, wrong. We'll need to actually call // the constructor or conversion operator, and then cope with the // standard conversions. ImpCastExprToType(From, ToType.getNonReferenceType(), ToType->isLValueReferenceType()); return false; case ImplicitConversionSequence::EllipsisConversion: assert(false && "Cannot perform an ellipsis conversion"); return false; case ImplicitConversionSequence::BadConversion: return true; } // Everything went well. return false; }
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is /// valid. /// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code /// like this: /// char *bytes = reinterpret_cast\<char*\>(int_ptr); void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange) { if (!DestType->isLValueReferenceType()) Self.DefaultFunctionArrayConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Reinterpret << SrcExpr->getType() << DestType << OpRange; }
/// ClassifyUnnamed - Return the classification of an expression yielding an /// unnamed value of the given type. This applies in particular to function /// calls and casts. static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { // In C, function calls are always rvalues. if (!Ctx.getLangOptions().CPlusPlus) return Cl::CL_PRValue; // C++ [expr.call]p10: A function call is an lvalue if the result type is an // lvalue reference type or an rvalue reference to function type, an xvalue // if the result type is an rvalue refernence to object type, and a prvalue // otherwise. if (T->isLValueReferenceType()) return Cl::CL_LValue; const RValueReferenceType *RV = T->getAs<RValueReferenceType>(); if (!RV) // Could still be a class temporary, though. return T->isRecordType() ? Cl::CL_ClassTemporary : Cl::CL_PRValue; return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue; }
bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, CastExpr::CastKind &Kind, bool FunctionalStyle) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (CastTy->isVoidType()) return false; // If the type is dependent, we won't do any other semantic analysis now. if (CastTy->isDependentType() || CastExpr->isTypeDependent()) return false; if (!CastTy->isLValueReferenceType()) DefaultFunctionArrayConversion(CastExpr); // C++ [expr.cast]p5: The conversions performed by // - a const_cast, // - a static_cast, // - a static_cast followed by a const_cast, // - a reinterpret_cast, or // - a reinterpret_cast followed by a const_cast, // can be performed using the cast notation of explicit type conversion. // [...] If a conversion can be interpreted in more than one of the ways // listed above, the interpretation that appears first in the list is used, // even if a cast resulting from that interpretation is ill-formed. // In plain language, this means trying a const_cast ... unsigned msg = diag::err_bad_cxx_cast_generic; TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,msg); if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, Kind, msg); if (tcr == TC_NotApplicable) { // ... and finally a reinterpret_cast, ignoring const. tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg); } } if (tcr != TC_Success && msg != 0) Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle) << CastExpr->getType() << CastTy << R; return tcr != TC_Success; }
/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making /// implicit conversions explicit and getting rid of data loss warnings. void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, CastExpr::CastKind &Kind) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { return; } if (!DestType->isLValueReferenceType()) Self.DefaultFunctionArrayConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, Kind, msg) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Static << SrcExpr->getType() << DestType << OpRange; }
static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef<Expr *> CallArgs) { QualType Ty = Callback->getType(); DeclRefExpr *Call = M.makeDeclRefExpr(Callback); CastKind CK; if (Ty->isRValueReferenceType()) { CK = CK_LValueToRValue; } else { assert(Ty->isLValueReferenceType()); CK = CK_FunctionToPointerDecay; Ty = C.getPointerType(Ty.getNonReferenceType()); } return new (C) CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK), /*args=*/CallArgs, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, /*SourceLocation=*/SourceLocation()); }
/// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType by following the standard /// conversion sequence SCS. Returns true if there was an error, false /// otherwise. The expression From is replaced with the converted /// expression. Flavor is the context in which we're performing this /// conversion, for use in error messages. bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, const char *Flavor) { // Overall FIXME: we are recomputing too many types here and doing // far too much extra work. What this means is that we need to keep // track of more information that is computed when we try the // implicit conversion initially, so that we don't need to recompute // anything here. QualType FromType = From->getType(); if (SCS.CopyConstructor) { // FIXME: Create a temporary object by calling the copy // constructor. ImpCastExprToType(From, ToType.getNonReferenceType(), ToType->isLValueReferenceType()); return false; } // Perform the first implicit conversion. switch (SCS.First) { case ICK_Identity: case ICK_Lvalue_To_Rvalue: // Nothing to do. break; case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); ImpCastExprToType(From, FromType); break; case ICK_Function_To_Pointer: if (Context.getCanonicalType(FromType) == Context.OverloadTy) { FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true); if (!Fn) return true; if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) return true; FixOverloadedFunctionReference(From, Fn); FromType = From->getType(); } FromType = Context.getPointerType(FromType); ImpCastExprToType(From, FromType); break; default: assert(false && "Improper first standard conversion"); break; } // Perform the second implicit conversion switch (SCS.Second) { case ICK_Identity: // Nothing to do. break; case ICK_Integral_Promotion: case ICK_Floating_Promotion: case ICK_Complex_Promotion: case ICK_Integral_Conversion: case ICK_Floating_Conversion: case ICK_Complex_Conversion: case ICK_Floating_Integral: case ICK_Complex_Real: case ICK_Compatible_Conversion: // FIXME: Go deeper to get the unqualified type! FromType = ToType.getUnqualifiedType(); ImpCastExprToType(From, FromType); break; case ICK_Pointer_Conversion: if (SCS.IncompatibleObjC) { // Diagnose incompatible Objective-C conversions Diag(From->getSourceRange().getBegin(), diag::ext_typecheck_convert_incompatible_pointer) << From->getType() << ToType << Flavor << From->getSourceRange(); } if (CheckPointerConversion(From, ToType)) return true; ImpCastExprToType(From, ToType); break; case ICK_Pointer_Member: if (CheckMemberPointerConversion(From, ToType)) return true; ImpCastExprToType(From, ToType); break; case ICK_Boolean_Conversion: FromType = Context.BoolTy; ImpCastExprToType(From, FromType); break; default: assert(false && "Improper second standard conversion"); break; } switch (SCS.Third) { case ICK_Identity: // Nothing to do. break; case ICK_Qualification: // FIXME: Not sure about lvalue vs rvalue here in the presence of // rvalue references. ImpCastExprToType(From, ToType.getNonReferenceType(), ToType->isLValueReferenceType()); break; default: assert(false && "Improper second standard conversion"); break; } return false; }
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) { // Visit all the children, which are the contents of the DeclGroupRef for (Stmt::child_iterator I = Node->child_begin(), E = Node->child_end(); I != E; ++I) { if (*I) { Expr* E = cast_or_null<Expr>(*I); if (!E || !IsArtificiallyDependent(E)) continue; //FIXME: don't assume there is only one decl. assert(Node->isSingleDecl() && "There is more that one decl in stmt"); VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl()); assert(CuredDecl && "Not a variable declaration!"); QualType CuredDeclTy = CuredDecl->getType(); // check if the case is sometype * somevar = init; // or some_builtin_type somevar = init; if (CuredDecl->hasInit() && (CuredDeclTy->isAnyPointerType() || !CuredDeclTy->isRecordType())) { *I = SubstituteUnknownSymbol(CuredDeclTy, CuredDecl->getInit()); continue; } // 1. Check whether this is the case of MyClass A(dep->symbol()) // 2. Insert the RuntimeUniverse's LifetimeHandler instance // 3. Change the A's initializer to *(MyClass*)instance.getMemory() // 4. Make A reference (&A) // 5. Set the new initializer of A if (CuredDeclTy->isLValueReferenceType()) continue; // Set Sema's Current DeclContext to the one we need DeclContext* OldDC = m_Sema->CurContext; m_Sema->CurContext = CuredDecl->getDeclContext(); ASTNodeInfo NewNode; // 2.1 Get unique name for the LifetimeHandler instance and // initialize it std::string UniqueName; createUniqueName(UniqueName); IdentifierInfo& II = m_Context->Idents.get(UniqueName); // Prepare the initialization Exprs. // We want to call LifetimeHandler(DynamicExprInfo* ExprInfo, // DeclContext DC, // const char* type) // Interpreter* interp) llvm::SmallVector<Expr*, 4> Inits; // Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo // DC, // "MyClass" // Interpreter* Interp) // Build Arg0 DynamicExprInfo Inits.push_back(BuildDynamicExprInfo(E)); // Build Arg1 DeclContext* DC QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl); Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy, (uint64_t)m_CurDeclContext) ); // Build Arg2 llvm::StringRef // Get the type of the type without specifiers PrintingPolicy Policy(m_Context->getLangOpts()); Policy.SuppressTagKeyword = 1; std::string Res; CuredDeclTy.getAsStringInternal(Res, Policy); Inits.push_back(ConstructConstCharPtrExpr(Res.c_str())); // Build Arg3 cling::Interpreter CXXScopeSpec CXXSS; DeclarationNameInfo NameInfo(m_gCling->getDeclName(), m_gCling->getLocStart()); Expr* gClingDRE = m_Sema->BuildDeclarationNameExpr(CXXSS, NameInfo ,m_gCling).take(); Inits.push_back(gClingDRE); // 2.3 Create a variable from LifetimeHandler. QualType HandlerTy = m_Context->getTypeDeclType(m_LifetimeHandlerDecl); TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(HandlerTy, m_NoSLoc); VarDecl* HandlerInstance = VarDecl::Create(*m_Context, CuredDecl->getDeclContext(), m_NoSLoc, m_NoSLoc, &II, HandlerTy, TSI, SC_None); // 2.4 Call the best-match constructor. The method does overload // resolution of the constructors and then initializes the new // variable with it ExprResult InitExprResult = m_Sema->ActOnParenListExpr(m_NoSLoc, m_NoELoc, Inits); m_Sema->AddInitializerToDecl(HandlerInstance, InitExprResult.take(), /*DirectInit*/ true, /*TypeMayContainAuto*/ false); // 2.5 Register the instance in the enclosing context CuredDecl->getDeclContext()->addDecl(HandlerInstance); NewNode.addNode(new (m_Context) DeclStmt(DeclGroupRef(HandlerInstance), m_NoSLoc, m_NoELoc) ); // 3.1 Build a DeclRefExpr, which holds the object DeclRefExpr* MemberExprBase = m_Sema->BuildDeclRefExpr(HandlerInstance, HandlerTy, VK_LValue, m_NoSLoc ).takeAs<DeclRefExpr>(); // 3.2 Create a MemberExpr to getMemory from its declaration. CXXScopeSpec SS; LookupResult MemberLookup(*m_Sema, m_LHgetMemoryDecl->getDeclName(), m_NoSLoc, Sema::LookupMemberName); // Add the declaration as if doesn't exist. // TODO: Check whether this is the most appropriate variant MemberLookup.addDecl(m_LHgetMemoryDecl, AS_public); MemberLookup.resolveKind(); Expr* MemberExpr = m_Sema->BuildMemberReferenceExpr(MemberExprBase, HandlerTy, m_NoSLoc, /*IsArrow=*/false, SS, m_NoSLoc, /*FirstQualifierInScope=*/0, MemberLookup, /*TemplateArgs=*/0 ).take(); // 3.3 Build the actual call Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext); Expr* theCall = m_Sema->ActOnCallExpr(S, MemberExpr, m_NoSLoc, MultiExprArg(), m_NoELoc).take(); // Cast to the type LHS type Expr* Result = utils::Synthesize::CStyleCastPtrExpr(m_Sema, CuredDeclTy, theCall); // Cast once more (dereference the cstyle cast) Result = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_Deref, Result).take(); // 4. CuredDecl->setType(m_Context->getLValueReferenceType(CuredDeclTy)); // 5. CuredDecl->setInit(Result); NewNode.addNode(Node); // Restore Sema's original DeclContext m_Sema->CurContext = OldDC; return NewNode; } } return ASTNodeInfo(Node, 0); }