static bool pointedUnqualifiedTypesAreEqual(QualType T1, QualType T2) { while ((T1->isPointerType() && T2->isPointerType()) || (T1->isReferenceType() && T2->isReferenceType())) { T1 = T1->getPointeeType(); T2 = T2->getPointeeType(); } return T1.getUnqualifiedType() == T2.getUnqualifiedType(); }
static bool needsConstCast(QualType SourceType, QualType DestType) { while ((SourceType->isPointerType() && DestType->isPointerType()) || (SourceType->isReferenceType() && DestType->isReferenceType())) { SourceType = SourceType->getPointeeType(); DestType = DestType->getPointeeType(); if (SourceType.isConstQualified() && !DestType.isConstQualified()) { return (SourceType->isPointerType() == DestType->isPointerType()) && (SourceType->isReferenceType() == DestType->isReferenceType()); } } return false; }
long long clang_Type_getSizeOf(CXType T) { if (T.kind == CXType_Invalid) return CXTypeLayoutError_Invalid; ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext(); QualType QT = GetQualType(T); // [expr.sizeof] p2: if reference type, return size of referenced type if (QT->isReferenceType()) QT = QT.getNonReferenceType(); // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete // enumeration // Note: We get the cxtype, not the cxcursor, so we can't call // FieldDecl->isBitField() // [expr.sizeof] p3: pointer ok, function not ok. // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error if (QT->isIncompleteType()) return CXTypeLayoutError_Incomplete; if (QT->isDependentType()) return CXTypeLayoutError_Dependent; if (!QT->isConstantSizeType()) return CXTypeLayoutError_NotConstantSize; // [gcc extension] lib/AST/ExprConstant.cpp:1372 // HandleSizeof : {voidtype,functype} == 1 // not handled by ASTContext.cpp:1313 getTypeInfoImpl if (QT->isVoidType() || QT->isFunctionType()) return 1; return Ctx.getTypeSizeInChars(QT).getQuantity(); }
void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) return; SVal RetVal = C.getSVal(RetE); const StackFrameContext *SFC = C.getStackFrame(); QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl()); if (RetVal.isUndef()) { // "return;" is modeled to evaluate to an UndefinedVal. Allow UndefinedVal // to be returned in functions returning void to support this pattern: // void foo() { // return; // } // void test() { // return foo(); // } if (RT.isNull() || !RT->isVoidType()) emitUndef(C, RetE); return; } if (RT.isNull()) return; if (RT->isReferenceType()) { checkReference(C, RetE, RetVal.castAs<DefinedOrUnknownSVal>()); return; } }
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr, bool PerformInit) { const Expr *Init = D.getInit(); QualType T = D.getType(); if (!T->isReferenceType()) { if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>()) (void)CGM.getOpenMPRuntime().EmitOMPThreadPrivateVarDefinition( &D, DeclPtr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), PerformInit, this); if (PerformInit) EmitDeclInit(*this, D, DeclPtr); if (CGM.isTypeConstant(D.getType(), true)) EmitDeclInvariant(*this, D, DeclPtr); else EmitDeclDestroy(*this, D, DeclPtr); return; } assert(PerformInit && "cannot have constant initializer which needs " "destruction for reference"); unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); RValue RV = EmitReferenceBindingToExpr(Init); EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T); }
SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // assert (!X.isUnknownOrUndef()); if (Loc::IsLocType(T) || T->isReferenceType()) return X; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (T->isUnionType()) return UnknownVal(); assert (T->isIntegerType()); BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned BitWidth = Eng.getContext().getTypeSize(T); if (!isa<loc::ConcreteInt>(X)) return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth); llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue(); V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T)); V.extOrTrunc(BitWidth); return nonloc::ConcreteInt(BasicVals.getValue(V)); }
void InnerPointerChecker::checkFunctionArguments(const CallEvent &Call, ProgramStateRef State, CheckerContext &C) const { if (const auto *FC = dyn_cast<AnyFunctionCall>(&Call)) { const FunctionDecl *FD = FC->getDecl(); if (!FD || !FD->isInStdNamespace()) return; for (unsigned I = 0, E = FD->getNumParams(); I != E; ++I) { QualType ParamTy = FD->getParamDecl(I)->getType(); if (!ParamTy->isReferenceType() || ParamTy->getPointeeType().isConstQualified()) continue; // In case of member operator calls, `this` is counted as an // argument but not as a parameter. bool isaMemberOpCall = isa<CXXMemberOperatorCall>(FC); unsigned ArgI = isaMemberOpCall ? I+1 : I; SVal Arg = FC->getArgSVal(ArgI); const auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(Arg.getAsRegion()); if (!ArgRegion) continue; markPtrSymbolsReleased(Call, State, ArgRegion, C); } } }
void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg, ExplodedNode *N) const { if (!BT_msg_ret) BT_msg_ret.reset( new BuiltinBug(this, "Receiver in message expression is 'nil'")); const ObjCMessageExpr *ME = msg.getOriginExpr(); QualType ResTy = msg.getResultType(); SmallString<200> buf; llvm::raw_svector_ostream os(buf); os << "The receiver of message '"; ME->getSelector().print(os); os << "' is nil"; if (ResTy->isReferenceType()) { os << ", which results in forming a null reference"; } else { os << " and returns a value of type '"; msg.getResultType().print(os, C.getLangOpts()); os << "' that will be garbage"; } auto report = llvm::make_unique<BugReport>(*BT_msg_ret, os.str(), N); report->addRange(ME->getReceiverRange()); // FIXME: This won't track "self" in messages to super. if (const Expr *receiver = ME->getInstanceReceiver()) { bugreporter::trackNullOrUndefValue(N, receiver, *report); } C.emitReport(std::move(report)); }
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { QualType type = LV.getType(); // FIXME: Ignore result? // FIXME: Are initializers affected by volatile? if (Dest.isZeroed() && isSimpleZero(E, CGF)) { // Storing "i32 0" to a zero'd memory location is a noop. } else if (isa<ImplicitValueInitExpr>(E)) { EmitNullInitializationToLValue(LV); } else if (type->isReferenceType()) { RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); CGF.EmitStoreThroughLValue(RV, LV); } else if (type->isAnyComplexType()) { CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); } else if (CGF.hasAggregateLLVMType(type)) { CGF.EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, Dest.isZeroed())); } else if (LV.isSimple()) { CGF.EmitScalarInit(E, /*D=*/0, LV, /*Captured=*/false); } else { CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV); } }
static bool isCallbackArg(SVal V, QualType T) { // If the parameter is 0, it's harmless. if (V.isZeroConstant()) return false; // If a parameter is a block or a callback, assume it can modify pointer. if (T->isBlockPointerType() || T->isFunctionPointerType() || T->isObjCSelType()) return true; // Check if a callback is passed inside a struct (for both, struct passed by // reference and by value). Dig just one level into the struct for now. if (T->isAnyPointerType() || T->isReferenceType()) T = T->getPointeeType(); if (const RecordType *RT = T->getAsStructureType()) { const RecordDecl *RD = RT->getDecl(); for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { QualType FieldT = I->getType(); if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType()) return true; } } return false; }
/// CheckAllocatedType - Checks that a type is suitable as the allocated type /// in a new-expression. /// dimension off and stores the size expression in ArraySize. bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an // abstract class type or array thereof. if (AllocType->isFunctionType()) return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type) << AllocType << 0 << D.getSourceRange(); else if (AllocType->isReferenceType()) return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type) << AllocType << 1 << D.getSourceRange(); else if (!AllocType->isDependentType() && RequireCompleteType(D.getSourceRange().getBegin(), AllocType, diag::err_new_incomplete_type, D.getSourceRange())) return true; else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType, diag::err_allocation_of_abstract_type)) return true; // Every dimension shall be of constant size. unsigned i = 1; while (const ArrayType *Array = Context.getAsArrayType(AllocType)) { if (!Array->isConstantArrayType()) { Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst) << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange(); return true; } AllocType = Array->getElementType(); ++i; } return false; }
SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // if (Loc::isLocType(castTy) || castTy->isReferenceType()) return val; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (castTy->isUnionType()) return UnknownVal(); if (castTy->isIntegerType()) { unsigned BitWidth = Context.getTypeSize(castTy); if (!isa<loc::ConcreteInt>(val)) return makeLocAsInteger(val, BitWidth); llvm::APSInt i = cast<loc::ConcreteInt>(val).getValue(); BasicVals.getAPSIntType(castTy).apply(i); return makeIntVal(i); } // All other cases: return 'UnknownVal'. This includes casting pointers // to floats, which is probably badness it itself, but this is a good // intermediate solution until we do something better. return UnknownVal(); }
RangeSet RangeConstraintManager::getRange(ProgramStateRef State, SymbolRef Sym) { if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym)) return *V; BasicValueFactory &BV = getBasicVals(); // If Sym is a difference of symbols A - B, then maybe we have range set // stored for B - A. if (const RangeSet *R = getRangeForMinusSymbol(State, Sym)) return R->Negate(BV, F); // Lazily generate a new RangeSet representing all possible values for the // given symbol type. QualType T = Sym->getType(); RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T)); // References are known to be non-zero. if (T->isReferenceType()) return assumeNonZero(BV, F, Sym, Result); // Known constraints on ranges of bitwise expressions. if (const SymIntExpr* SIE = dyn_cast<SymIntExpr>(Sym)) return applyBitwiseConstraints(BV, F, Result, SIE); return Result; }
SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // if (Loc::isLocType(castTy) || castTy->isReferenceType()) return val; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (castTy->isUnionType()) return UnknownVal(); // Casting a Loc to a bool will almost always be true, // unless this is a weak function or a symbolic region. if (castTy->isBooleanType()) { switch (val.getSubKind()) { case loc::MemRegionValKind: { const MemRegion *R = val.castAs<loc::MemRegionVal>().getRegion(); if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R)) if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl())) if (FD->isWeak()) // FIXME: Currently we are using an extent symbol here, // because there are no generic region address metadata // symbols to use, only content metadata. return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR)); if (const SymbolicRegion *SymR = R->getSymbolicBase()) return nonloc::SymbolVal(SymR->getSymbol()); // FALL-THROUGH LLVM_FALLTHROUGH; } case loc::GotoLabelKind: // Labels and non-symbolic memory regions are always true. return makeTruthVal(true, castTy); } } if (castTy->isIntegralOrEnumerationType()) { unsigned BitWidth = Context.getTypeSize(castTy); if (!val.getAs<loc::ConcreteInt>()) return makeLocAsInteger(val, BitWidth); llvm::APSInt i = val.castAs<loc::ConcreteInt>().getValue(); BasicVals.getAPSIntType(castTy).apply(i); return makeIntVal(i); } // All other cases: return 'UnknownVal'. This includes casting pointers // to floats, which is probably badness it itself, but this is a good // intermediate solution until we do something better. return UnknownVal(); }
static bool isPointerToConst(const ParmVarDecl *ParamDecl) { QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); if (PointeeTy != QualType() && PointeeTy.isConstQualified() && !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { return true; } return false; }
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr, bool PerformInit) { const Expr *Init = D.getInit(); QualType T = D.getType(); // The address space of a static local variable (DeclPtr) may be different // from the address space of the "this" argument of the constructor. In that // case, we need an addrspacecast before calling the constructor. // // struct StructWithCtor { // __device__ StructWithCtor() {...} // }; // __device__ void foo() { // __shared__ StructWithCtor s; // ... // } // // For example, in the above CUDA code, the static local variable s has a // "shared" address space qualifier, but the constructor of StructWithCtor // expects "this" in the "generic" address space. unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T); unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace(); if (ActualAddrSpace != ExpectedAddrSpace) { llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T); llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace); DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy); } ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D)); if (!T->isReferenceType()) { if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && D.hasAttr<OMPThreadPrivateDeclAttr>()) { (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition( &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), PerformInit, this); } if (PerformInit) EmitDeclInit(*this, D, DeclAddr); if (CGM.isTypeConstant(D.getType(), true)) EmitDeclInvariant(*this, D, DeclPtr); else EmitDeclDestroy(*this, D, DeclAddr); return; } assert(PerformInit && "cannot have constant initializer which needs " "destruction for reference"); RValue RV = EmitReferenceBindingToExpr(Init); EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T); }
PathDiagnosticPiece * UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { ProgramStateRef State = N->getState(); ProgramPoint ProgLoc = N->getLocation(); // We are only interested in visiting CallEnter nodes. Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>(); if (!CEnter) return 0; // Check if one of the arguments is the region the visitor is tracking. CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); unsigned Idx = 0; for (CallEvent::param_iterator I = Call->param_begin(), E = Call->param_end(); I != E; ++I, ++Idx) { const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); // Are we tracking the argument or its subregion? if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) continue; // Check the function parameter type. const ParmVarDecl *ParamDecl = *I; assert(ParamDecl && "Formal parameter has no decl?"); QualType T = ParamDecl->getType(); if (!(T->isAnyPointerType() || T->isReferenceType())) { // Function can only change the value passed in by address. continue; } // If it is a const pointer value, the function does not intend to // change the value. if (T->getPointeeType().isConstQualified()) continue; // Mark the call site (LocationContext) as interesting if the value of the // argument is undefined or '0'/'NULL'. SVal BoundVal = State->getSVal(R); if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { BR.markInteresting(CEnter->getCalleeContext()); return 0; } } return 0; }
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // For an assignment to work, the value on the right has // to be compatible with the value on the left. assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), E->getRHS()->getType()) && "Invalid assignment"); if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getLHS())) if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) if (VD->hasAttr<BlocksAttr>() && E->getRHS()->HasSideEffects(CGF.getContext())) { // When __block variable on LHS, the RHS must be evaluated first // as it may change the 'forwarding' field via call to Block_copy. LValue RHS = CGF.EmitLValue(E->getRHS()); LValue LHS = CGF.EmitLValue(E->getLHS()); bool GCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) GCollection = TypeRequiresGCollection(E->getLHS()->getType()); Dest = AggValueSlot::forLValue(LHS, true, GCollection); EmitFinalDestCopy(E, RHS, true); return; } LValue LHS = CGF.EmitLValue(E->getLHS()); // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { const ObjCPropertyRefExpr *RE = LHS.getPropertyRefExpr(); QualType ArgType = RE->getSetterArgType(); RValue Src; if (ArgType->isReferenceType()) Src = CGF.EmitReferenceBindingToExpr(E->getRHS(), 0); else { AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), Slot); Src = Slot.asRValue(); } CGF.EmitStoreThroughPropertyRefLValue(Src, LHS); } else { bool GCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) GCollection = TypeRequiresGCollection(E->getLHS()->getType()); // Codegen the RHS so that it stores directly into the LHS. AggValueSlot LHSSlot = AggValueSlot::forLValue(LHS, true, GCollection); CGF.EmitAggExpr(E->getRHS(), LHSSlot, false); EmitFinalDestCopy(E, LHS, true); } }
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr) { const Expr *Init = D.getInit(); QualType T = D.getType(); if (!T->isReferenceType()) { EmitDeclInit(*this, D, DeclPtr); EmitDeclDestroy(*this, D, DeclPtr); return; } RValue RV = EmitReferenceBindingToExpr(Init, &D); EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T); }
/// Check if the given type is a valid base type to be used in access tags. static bool isValidBaseType(QualType QTy) { if (QTy->isReferenceType()) return false; if (const RecordType *TTy = QTy->getAs<RecordType>()) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); // Incomplete types are not valid base access types. if (!RD) return false; if (RD->hasFlexibleArrayMember()) return false; // RD can be struct, union, class, interface or enum. // For now, we only handle struct and class. if (RD->isStruct() || RD->isClass()) return true; } return false; }
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV, QualType T) { // FIXME: Ignore result? // FIXME: Are initializers affected by volatile? if (isa<ImplicitValueInitExpr>(E)) { EmitNullInitializationToLValue(LV, T); } else if (T->isReferenceType()) { RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); CGF.EmitStoreThroughLValue(RV, LV, T); } else if (T->isAnyComplexType()) { CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); } else if (CGF.hasAggregateLLVMType(T)) { CGF.EmitAnyExpr(E, LV.getAddress(), false); } else { CGF.EmitStoreThroughLValue(CGF.EmitAnyExpr(E), LV, T); } }
void edmChecker::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::AnalysisManager& mgr, clang::ento::BugReporter &BR) const { const clang::SourceManager &SM = BR.getSourceManager(); clang::ento::PathDiagnosticLocation DLoc =clang::ento::PathDiagnosticLocation::createBegin( RD, SM ); if ( !m_exception.reportClass( DLoc, BR ) ) return; // Check the class methods (member methods). for (clang::CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { if ( !llvm::isa<clang::CXXMethodDecl>((*I)) ) continue; clang::CXXMethodDecl * MD = llvm::cast<clang::CXXMethodDecl>((*I)); if ( MD->getNameAsString() == "beginRun" || MD->getNameAsString() == "endRun" || MD->getNameAsString() == "beginLuminosityBlock" || MD->getNameAsString() == "endLuminosityBlock" ) { // llvm::errs()<<MD->getQualifiedNameAsString()<<"\n"; for (auto J=RD->bases_begin(), F=RD->bases_end();J != F; ++J) { std::string name = J->getType()->castAs<RecordType>()->getDecl()->getQualifiedNameAsString(); // llvm::errs()<<RD->getQualifiedNameAsString()<<"\n"; // llvm::errs() << "inherits from " <<name<<"\n"; if (name=="edm::EDProducer" || name=="edm::EDFilter") { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << RD->getQualifiedNameAsString() << " inherits from edm::EDProducer or edm::EDFilter"; os << "\n"; llvm::errs()<<os.str(); CXXMethodDecl::param_iterator I = MD->param_begin(); ParmVarDecl * PVD = *(I); QualType PQT = PVD->getType(); if ( PQT->isReferenceType() ) { QualType RQT = PQT->getPointeeType(); if (RQT.isConstQualified()) continue; } clang::ento::PathDiagnosticLocation ELoc =clang::ento::PathDiagnosticLocation::createBegin( MD, SM ); clang::SourceLocation SL = MD->getLocStart(); BR.EmitBasicReport(MD, "Class Checker : inherits from edm::EDProducer or edm::EDFilter","optional",os.str(),ELoc,SL); } } } } } //end of class
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr) { const Expr *Init = D.getInit(); QualType T = D.getType(); if (!T->isReferenceType()) { EmitDeclInit(*this, D, DeclPtr); return; } if (Init->isLvalue(getContext()) == Expr::LV_Valid) { RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true); EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T); return; } ErrorUnsupported(Init, "global variable that binds reference to a non-lvalue"); }
static RValue PerformReturnAdjustment(CodeGenFunction &CGF, QualType ResultType, RValue RV, const ThunkInfo &Thunk) { // Emit the return adjustment. bool NullCheckValue = !ResultType->isReferenceType(); llvm::BasicBlock *AdjustNull = nullptr; llvm::BasicBlock *AdjustNotNull = nullptr; llvm::BasicBlock *AdjustEnd = nullptr; llvm::Value *ReturnValue = RV.getScalarVal(); if (NullCheckValue) { AdjustNull = CGF.createBasicBlock("adjust.null"); AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); AdjustEnd = CGF.createBasicBlock("adjust.end"); llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); CGF.EmitBlock(AdjustNotNull); } auto ClassDecl = ResultType->getPointeeType()->getAsCXXRecordDecl(); auto ClassAlign = CGF.CGM.getClassPointerAlignment(ClassDecl); ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF, Address(ReturnValue, ClassAlign), Thunk.Return); if (NullCheckValue) { CGF.Builder.CreateBr(AdjustEnd); CGF.EmitBlock(AdjustNull); CGF.Builder.CreateBr(AdjustEnd); CGF.EmitBlock(AdjustEnd); llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); PHI->addIncoming(ReturnValue, AdjustNotNull); PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), AdjustNull); ReturnValue = PHI; } return RValue::get(ReturnValue); }
long long clang_Type_getAlignOf(CXType T) { if (T.kind == CXType_Invalid) return CXTypeLayoutError_Invalid; ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext(); QualType QT = GetQualType(T); // [expr.alignof] p1: return size_t value for complete object type, reference // or array. // [expr.alignof] p3: if reference type, return size of referenced type if (QT->isReferenceType()) QT = QT.getNonReferenceType(); if (QT->isIncompleteType()) return CXTypeLayoutError_Incomplete; if (QT->isDependentType()) return CXTypeLayoutError_Dependent; // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1 // if (QT->isVoidType()) return 1; return Ctx.getTypeAlignInChars(QT).getQuantity(); }
static RValue PerformReturnAdjustment(CodeGenFunction &CGF, QualType ResultType, RValue RV, const ThunkInfo &Thunk) { // Emit the return adjustment. bool NullCheckValue = !ResultType->isReferenceType(); llvm::BasicBlock *AdjustNull = 0; llvm::BasicBlock *AdjustNotNull = 0; llvm::BasicBlock *AdjustEnd = 0; llvm::Value *ReturnValue = RV.getScalarVal(); if (NullCheckValue) { AdjustNull = CGF.createBasicBlock("adjust.null"); AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); AdjustEnd = CGF.createBasicBlock("adjust.end"); llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); CGF.EmitBlock(AdjustNotNull); } ReturnValue = PerformTypeAdjustment(CGF, ReturnValue, Thunk.Return.NonVirtual, Thunk.Return.VBaseOffsetOffset, /*IsReturnAdjustment*/true); if (NullCheckValue) { CGF.Builder.CreateBr(AdjustEnd); CGF.EmitBlock(AdjustNull); CGF.Builder.CreateBr(AdjustEnd); CGF.EmitBlock(AdjustEnd); llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); PHI->addIncoming(ReturnValue, AdjustNotNull); PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), AdjustNull); ReturnValue = PHI; } return RValue::get(ReturnValue); }
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV, QualType T) { // FIXME: Ignore result? // FIXME: Are initializers affected by volatile? if (Dest.isZeroed() && isSimpleZero(E, CGF)) { // Storing "i32 0" to a zero'd memory location is a noop. } else if (isa<ImplicitValueInitExpr>(E)) { EmitNullInitializationToLValue(LV, T); } else if (T->isReferenceType()) { RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); CGF.EmitStoreThroughLValue(RV, LV, T); } else if (T->isAnyComplexType()) { CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); } else if (CGF.hasAggregateLLVMType(T)) { CGF.EmitAggExpr(E, AggValueSlot::forAddr(LV.getAddress(), false, true, false, Dest.isZeroed())); } else { CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV, T); } }
/// \brief Build a pointer type. /// /// \param T The type to which we'll be building a pointer. /// /// \param Quals The cvr-qualifiers to be applied to the pointer type. /// /// \param Loc The location of the entity whose type involves this /// pointer type or, if there is no such entity, the location of the /// type that will have pointer type. /// /// \param Entity The name of the entity that involves the pointer /// type, if known. /// /// \returns A suitable pointer type, if there are no /// errors. Otherwise, returns a NULL type. QualType Sema::BuildPointerType(QualType T, unsigned Quals, SourceLocation Loc, DeclarationName Entity) { if (T->isReferenceType()) { // C++ 8.3.2p4: There shall be no ... pointers to references ... Diag(Loc, diag::err_illegal_decl_pointer_to_reference) << getPrintableNameForEntity(Entity); return QualType(); } // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) { Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) << T; Quals &= ~QualType::Restrict; } // Build the pointer type. return Context.getPointerType(T).getQualifiedType(Quals); }
void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) return; SVal RetVal = C.getSVal(RetE); const StackFrameContext *SFC = C.getStackFrame(); QualType RT = CallEvent::getDeclaredResultType(SFC->getDecl()); if (RetVal.isUndef()) { // "return;" is modeled to evaluate to an UndefinedVal. Allow UndefinedVal // to be returned in functions returning void to support this pattern: // void foo() { // return; // } // void test() { // return foo(); // } if (!RT.isNull() && RT->isVoidType()) return; // Not all blocks have explicitly-specified return types; if the return type // is not available, but the return value expression has 'void' type, assume // Sema already checked it. if (RT.isNull() && isa<BlockDecl>(SFC->getDecl()) && RetE->getType()->isVoidType()) return; emitUndef(C, RetE); return; } if (RT.isNull()) return; if (RT->isReferenceType()) { checkReference(C, RetE, RetVal.castAs<DefinedOrUnknownSVal>()); return; } }
/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2 /// is valid: /// /// An expression e can be explicitly converted to a type T using a /// @c static_cast if the declaration "T t(e);" is well-formed [...]. TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg) { if (DestType->isReferenceType()) { // At this point of CheckStaticCast, if the destination is a reference, // this has to work. There is no other way that works. // On the other hand, if we're checking a C-style cast, we've still got // the reinterpret_cast way. In that case, we pass an ICS so we don't // get error messages. ImplicitConversionSequence ICS; bool failed = Self.CheckReferenceInit(SrcExpr, DestType, CStyle ? &ICS : 0); if (!failed) return TC_Success; if (CStyle) return TC_NotApplicable; // If we didn't pass the ICS, we already got an error message. msg = 0; return TC_Failed; } if (DestType->isRecordType()) { // There are no further possibilities for the target type being a class, // neither in static_cast nor in a C-style cast. So we can fail here. // FIXME: We need to store this constructor in the AST. if (Self.PerformInitializationByConstructor(DestType, &SrcExpr, 1, OpRange.getBegin(), OpRange, DeclarationName(), Sema::IK_Direct)) return TC_Success; // The function already emitted an error. msg = 0; return TC_Failed; } // FIXME: To get a proper error from invalid conversions here, we need to // reimplement more of this. // FIXME: This does not actually perform the conversion, and thus does not // check for ambiguity or access. ImplicitConversionSequence ICS = Self.TryImplicitConversion( SrcExpr, DestType); return ICS.ConversionKind == ImplicitConversionSequence::BadConversion ? TC_NotApplicable : TC_Success; }