#include "UsedDeclVisitor.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/RISCVIntrinsicManager.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Sema/TypoCorrection.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/TimeProfiler.h"
using namespace clang;
using namespace sema;
SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
}
ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
DarwinSDKInfo *
Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
StringRef Platform) {
auto *SDKInfo = getDarwinSDKInfoForAvailabilityChecking();
if (!SDKInfo && !WarnedDarwinSDKInfoMissing) {
Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking)
<< Platform;
WarnedDarwinSDKInfoMissing = true;
}
return SDKInfo;
}
DarwinSDKInfo *Sema::getDarwinSDKInfoForAvailabilityChecking() {
if (CachedDarwinSDKInfo)
return CachedDarwinSDKInfo->get();
auto SDKInfo = parseDarwinSDKInfo(
PP.getFileManager().getVirtualFileSystem(),
PP.getHeaderSearchInfo().getHeaderSearchOpts().Sysroot);
if (SDKInfo && *SDKInfo) {
CachedDarwinSDKInfo = std::make_unique<DarwinSDKInfo>(std::move(**SDKInfo));
return CachedDarwinSDKInfo->get();
}
if (!SDKInfo)
llvm::consumeError(SDKInfo.takeError());
CachedDarwinSDKInfo = std::unique_ptr<DarwinSDKInfo>();
return nullptr;
}
IdentifierInfo *
Sema::InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
unsigned int Index) {
std::string InventedName;
llvm::raw_string_ostream OS(InventedName);
if (!ParamName)
OS << "auto:" << Index + 1;
else
OS << ParamName->getName() << ":auto";
OS.flush();
return &Context.Idents.get(OS.str());
}
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
Policy.Bool = BoolMacro->isObjectLike() &&
BoolMacro->getNumTokens() == 1 &&
BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
}
}
Policy.EntireContentsOfLargeArray = false;
return Policy;
}
void Sema::ActOnTranslationUnitScope(Scope *S) {
TUScope = S;
PushDeclContext(S, Context.getTranslationUnitDecl());
}
namespace clang {
namespace sema {
class SemaPPCallbacks : public PPCallbacks {
Sema *S = nullptr;
llvm::SmallVector<SourceLocation, 8> IncludeStack;
public:
void set(Sema &S) { this->S = &S; }
void reset() { S = nullptr; }
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override {
if (!S)
return;
switch (Reason) {
case EnterFile: {
SourceManager &SM = S->getSourceManager();
SourceLocation IncludeLoc = SM.getIncludeLoc(SM.getFileID(Loc));
if (IncludeLoc.isValid()) {
if (llvm::timeTraceProfilerEnabled()) {
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc));
llvm::timeTraceProfilerBegin(
"Source", FE != nullptr ? FE->getName() : StringRef("<unknown>"));
}
IncludeStack.push_back(IncludeLoc);
S->DiagnoseNonDefaultPragmaAlignPack(
Sema::PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude,
IncludeLoc);
}
break;
}
case ExitFile:
if (!IncludeStack.empty()) {
if (llvm::timeTraceProfilerEnabled())
llvm::timeTraceProfilerEnd();
S->DiagnoseNonDefaultPragmaAlignPack(
Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit,
IncludeStack.pop_back_val());
}
break;
default:
break;
}
}
};
} }
const unsigned Sema::MaxAlignmentExponent;
const uint64_t Sema::MaximumAlignment;
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
: ExternalSource(nullptr), isMultiplexExternalSource(false),
CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
SourceMgr(PP.getSourceManager()), CollectStats(false),
CodeCompleter(CodeCompleter), CurContext(nullptr),
OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
VtorDispStack(LangOpts.getVtorDispMode()),
AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()),
CurInitSeg(nullptr), VisContext(nullptr),
PragmaAttributeCurrentTargetDecl(nullptr),
IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
MSVCGuidDecl(nullptr), StdSourceLocationImplDecl(nullptr),
NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr),
StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
TUKind(TUKind), NumSFINAEErrors(0),
FullyCheckedComparisonCategories(
static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
SatisfactionCache(Context), AccessCheckingSFINAE(false),
InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
assert(pp.TUKind == TUKind);
TUScope = nullptr;
isConstantEvaluatedOverride = false;
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = nullptr;
if (getLangOpts().ObjC)
NSAPIObj.reset(new NSAPI(Context));
if (getLangOpts().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);
ExprEvalContexts.emplace_back(
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
nullptr, ExpressionEvaluationContextRecord::EK_Other);
InitDataSharingAttributesStack();
std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
std::make_unique<sema::SemaPPCallbacks>();
SemaPPCallbackHandler = Callbacks.get();
PP.addPPCallbacks(std::move(Callbacks));
SemaPPCallbackHandler->set(*this);
CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod());
}
void Sema::anchor() {}
void Sema::addImplicitTypedef(StringRef Name, QualType T) {
DeclarationName DN = &Context.Idents.get(Name);
if (IdResolver.begin(DN) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitTypedef(T, Name), TUScope);
}
void Sema::Initialize() {
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
SC->InitializeSema(*this);
if (ExternalSemaSource *ExternalSema
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
ExternalSema->InitializeSema(*this);
VAListTagName = PP.getIdentifierInfo("__va_list_tag");
if (!TUScope)
return;
if (Context.getTargetInfo().hasInt128Type() ||
(Context.getAuxTargetInfo() &&
Context.getAuxTargetInfo()->hasInt128Type())) {
DeclarationName Int128 = &Context.Idents.get("__int128_t");
if (IdResolver.begin(Int128) == IdResolver.end())
PushOnScopeChains(Context.getInt128Decl(), TUScope);
DeclarationName UInt128 = &Context.Idents.get("__uint128_t");
if (IdResolver.begin(UInt128) == IdResolver.end())
PushOnScopeChains(Context.getUInt128Decl(), TUScope);
}
if (getLangOpts().ObjC) {
DeclarationName SEL = &Context.Idents.get("SEL");
if (IdResolver.begin(SEL) == IdResolver.end())
PushOnScopeChains(Context.getObjCSelDecl(), TUScope);
DeclarationName Id = &Context.Idents.get("id");
if (IdResolver.begin(Id) == IdResolver.end())
PushOnScopeChains(Context.getObjCIdDecl(), TUScope);
DeclarationName Class = &Context.Idents.get("Class");
if (IdResolver.begin(Class) == IdResolver.end())
PushOnScopeChains(Context.getObjCClassDecl(), TUScope);
DeclarationName Protocol = &Context.Idents.get("Protocol");
if (IdResolver.begin(Protocol) == IdResolver.end())
PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
}
DeclarationName ConstantString = &Context.Idents.get("__NSConstantString");
if (IdResolver.begin(ConstantString) == IdResolver.end())
PushOnScopeChains(Context.getCFConstantStringDecl(), TUScope);
if (getLangOpts().MSVCCompat) {
if (getLangOpts().CPlusPlus &&
IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
TUScope);
addImplicitTypedef("size_t", Context.getSizeType());
}
if (getLangOpts().OpenCL) {
getOpenCLOptions().addSupport(
Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
auto OCLCompatibleVersion = getLangOpts().getOpenCLCompatibleVersion();
if (OCLCompatibleVersion >= 200) {
if (getLangOpts().OpenCLCPlusPlus || getLangOpts().Blocks) {
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
addImplicitTypedef("queue_t", Context.OCLQueueTy);
}
if (getLangOpts().OpenCLPipes)
addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
addImplicitTypedef("atomic_float",
Context.getAtomicType(Context.FloatTy));
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
auto AddPointerSizeDependentTypes = [&]() {
auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
auto AtomicPtrDiffT =
Context.getAtomicType(Context.getPointerDiffType());
addImplicitTypedef("atomic_size_t", AtomicSizeT);
addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
};
if (Context.getTypeSize(Context.getSizeType()) == 32) {
AddPointerSizeDependentTypes();
}
if (getOpenCLOptions().isSupported("cl_khr_fp16", getLangOpts())) {
auto AtomicHalfT = Context.getAtomicType(Context.HalfTy);
addImplicitTypedef("atomic_half", AtomicHalfT);
}
std::vector<QualType> Atomic64BitTypes;
if (getOpenCLOptions().isSupported("cl_khr_int64_base_atomics",
getLangOpts()) &&
getOpenCLOptions().isSupported("cl_khr_int64_extended_atomics",
getLangOpts())) {
if (getOpenCLOptions().isSupported("cl_khr_fp64", getLangOpts())) {
auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
addImplicitTypedef("atomic_double", AtomicDoubleT);
Atomic64BitTypes.push_back(AtomicDoubleT);
}
auto AtomicLongT = Context.getAtomicType(Context.LongTy);
auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
addImplicitTypedef("atomic_long", AtomicLongT);
addImplicitTypedef("atomic_ulong", AtomicULongT);
if (Context.getTypeSize(Context.getSizeType()) == 64) {
AddPointerSizeDependentTypes();
}
}
}
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \
addImplicitTypedef(#ExtType, Context.Id##Ty); \
}
#include "clang/Basic/OpenCLExtensionTypes.def"
}
if (Context.getTargetInfo().hasAArch64SVETypes()) {
#define SVE_TYPE(Name, Id, SingletonId) \
addImplicitTypedef(Name, Context.SingletonId);
#include "clang/Basic/AArch64SVEACLETypes.def"
}
if (Context.getTargetInfo().getTriple().isPPC64()) {
#define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \
addImplicitTypedef(#Name, Context.Id##Ty);
#include "clang/Basic/PPCTypes.def"
#define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \
addImplicitTypedef(#Name, Context.Id##Ty);
#include "clang/Basic/PPCTypes.def"
}
if (Context.getTargetInfo().hasRISCVVTypes()) {
#define RVV_TYPE(Name, Id, SingletonId) \
addImplicitTypedef(Name, Context.SingletonId);
#include "clang/Basic/RISCVVTypes.def"
}
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
if (IdResolver.begin(MSVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
}
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
}
Sema::~Sema() {
assert(InstantiatingSpecializations.empty() &&
"failed to clean up an InstantiatingTemplate?");
if (VisContext) FreeVisContext();
for (sema::FunctionScopeInfo *FSI : FunctionScopes)
delete FSI;
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
SC->ForgetSema();
if (ExternalSemaSource *ExternalSema
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
ExternalSema->ForgetSema();
if (isMultiplexExternalSource)
delete ExternalSource;
std::vector<ConstraintSatisfaction *> Satisfactions;
Satisfactions.reserve(Satisfactions.size());
for (auto &Node : SatisfactionCache)
Satisfactions.push_back(&Node);
for (auto *Node : Satisfactions)
delete Node;
threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);
DestroyDataSharingAttributesStack();
SemaPPCallbackHandler->reset();
}
void Sema::warnStackExhausted(SourceLocation Loc) {
if (!WarnedStackExhausted) {
Diag(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}
void Sema::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
}
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
UnavailableAttr::ImplicitReason reason) {
FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
if (!fn) return false;
if (inTemplateInstantiation())
return false;
if (!Context.getSourceManager().isInSystemHeader(loc))
return false;
if (fn->hasAttr<UnavailableAttr>()) return true;
fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc));
return true;
}
ASTMutationListener *Sema::getASTMutationListener() const {
return getASTConsumer().GetASTMutationListener();
}
void Sema::addExternalSource(ExternalSemaSource *E) {
assert(E && "Cannot use with NULL ptr");
if (!ExternalSource) {
ExternalSource = E;
return;
}
if (isMultiplexExternalSource)
static_cast<MultiplexExternalSemaSource*>(ExternalSource)->addSource(*E);
else {
ExternalSource = new MultiplexExternalSemaSource(*ExternalSource, *E);
isMultiplexExternalSource = true;
}
}
void Sema::PrintStats() const {
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
BumpAlloc.PrintStats();
AnalysisWarnings.PrintStats();
}
void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
QualType SrcType,
SourceLocation Loc) {
Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
*ExprNullability != NullabilityKind::NullableResult))
return;
Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
return;
Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType;
}
void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
E->getBeginLoc()))
return;
if (!getLangOpts().CPlusPlus11)
return;
if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
return;
if (E->IgnoreParenImpCasts()->getType()->isNullPtrType())
return;
if (!CodeSynthesisContexts.empty() &&
CodeSynthesisContexts.back().Kind ==
CodeSynthesisContext::RewritingOperatorAsSpaceship)
return;
SourceLocation MaybeMacroLoc = E->getBeginLoc();
if (Diags.getSuppressSystemWarnings() &&
SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
!findMacroSpelling(MaybeMacroLoc, "NULL"))
return;
Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant)
<< FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
}
ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
CastKind Kind, ExprValueKind VK,
const CXXCastPath *BasePath,
CheckedConversionKind CCK) {
#ifndef NDEBUG
if (VK == VK_PRValue && !E->isPRValue()) {
switch (Kind) {
default:
llvm_unreachable(
("can't implicitly cast glvalue to prvalue with this cast "
"kind: " +
std::string(CastExpr::getCastKindName(Kind)))
.c_str());
case CK_Dependent:
case CK_LValueToRValue:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_ToVoid:
case CK_NonAtomicToAtomic:
break;
}
}
assert((VK == VK_PRValue || Kind == CK_Dependent || !E->isPRValue()) &&
"can't cast prvalue to glvalue");
#endif
diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
diagnoseZeroToNullptrConversion(Kind, E);
QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
if (ExprTy == TypeTy)
return E;
if (Kind == CK_ArrayToPointerDecay) {
if (getLangOpts().CPlusPlus && E->isPRValue()) {
ExprResult Materialized = CreateMaterializeTemporaryExpr(
E->getType(), E, !getLangOpts().CPlusPlus11);
if (Materialized.isInvalid())
return ExprError();
E = Materialized.get();
}
if (VK == VK_PRValue && !getLangOpts().CPlusPlus && !E->isPRValue()) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
if (VD->getStorageClass() == SC_Register) {
Diag(E->getExprLoc(), diag::err_typecheck_address_of)
<< 3 << E->getSourceRange();
return ExprError();
}
}
}
}
}
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
ImpCast->setValueKind(VK);
return E;
}
}
return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK,
CurFPFeatureOverrides());
}
CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
switch (ScalarTy->getScalarTypeKind()) {
case Type::STK_Bool: return CK_NoOp;
case Type::STK_CPointer: return CK_PointerToBoolean;
case Type::STK_BlockPointer: return CK_PointerToBoolean;
case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean;
case Type::STK_MemberPointer: return CK_MemberPointerToBoolean;
case Type::STK_Integral: return CK_IntegralToBoolean;
case Type::STK_Floating: return CK_FloatingToBoolean;
case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
case Type::STK_FixedPoint: return CK_FixedPointToBoolean;
}
llvm_unreachable("unknown scalar type kind");
}
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
if (D->isExternallyVisible())
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate())
for (const auto *Spec : Template->specializations())
if (ShouldRemoveFromUnused(SemaRef, Spec))
return true;
const FunctionDecl *DeclToCheck;
if (FD->hasBody(DeclToCheck))
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
DeclToCheck = FD->getMostRecentDecl();
if (DeclToCheck != FD)
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
}
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->isReferenced() &&
VD->mightBeUsableInConstantExpressions(SemaRef->Context))
return true;
if (VarTemplateDecl *Template = VD->getDescribedVarTemplate())
for (const auto *Spec : Template->specializations())
if (ShouldRemoveFromUnused(SemaRef, Spec))
return true;
const VarDecl *DeclToCheck = VD->getDefinition();
if (DeclToCheck)
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
DeclToCheck = VD->getMostRecentDecl();
if (DeclToCheck != VD)
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
}
return false;
}
static bool isFunctionOrVarDeclExternC(NamedDecl *ND) {
if (auto *FD = dyn_cast<FunctionDecl>(ND))
return FD->isExternC();
return cast<VarDecl>(ND)->isExternC();
}
bool Sema::isExternalWithNoLinkageType(ValueDecl *VD) {
return getLangOpts().CPlusPlus && VD->hasExternalFormalLinkage() &&
!isExternalFormalLinkage(VD->getType()->getLinkage()) &&
!isFunctionOrVarDeclExternC(VD);
}
void Sema::getUndefinedButUsed(
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
for (const auto &UndefinedUse : UndefinedButUsed) {
NamedDecl *ND = UndefinedUse.first;
if (ND->isInvalidDecl()) continue;
if (ND->hasAttr<WeakRefAttr>()) continue;
if (isa<CXXDeductionGuideDecl>(ND))
continue;
if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
continue;
}
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
if (FD->isExternallyVisible() &&
!isExternalWithNoLinkageType(FD) &&
!FD->getMostRecentDecl()->isInlined() &&
!FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (FD->getBuiltinID())
continue;
} else {
auto *VD = cast<VarDecl>(ND);
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
continue;
if (VD->isExternallyVisible() &&
!isExternalWithNoLinkageType(VD) &&
!VD->getMostRecentDecl()->isInline() &&
!VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (VD->isKnownToBeDefined())
continue;
}
Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
}
}
static void checkUndefinedButUsed(Sema &S) {
if (S.UndefinedButUsed.empty()) return;
SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
S.getUndefinedButUsed(Undefined);
if (Undefined.empty()) return;
for (auto Undef : Undefined) {
ValueDecl *VD = cast<ValueDecl>(Undef.first);
SourceLocation UseLoc = Undef.second;
if (S.isExternalWithNoLinkageType(VD)) {
S.Diag(VD->getLocation(), isExternallyVisible(VD->getType()->getLinkage())
? diag::ext_undefined_internal_type
: diag::err_undefined_internal_type)
<< isa<VarDecl>(VD) << VD;
} else if (!VD->isExternallyVisible()) {
bool IsImplicitBase = false;
if (const auto *BaseD = dyn_cast<FunctionDecl>(VD)) {
auto *DVAttr = BaseD->getAttr<OMPDeclareVariantAttr>();
if (DVAttr && !DVAttr->getTraitInfo().isExtensionActive(
llvm::omp::TraitProperty::
implementation_extension_disable_implicit_base)) {
const auto *Func = cast<FunctionDecl>(
cast<DeclRefExpr>(DVAttr->getVariantFuncRef())->getDecl());
IsImplicitBase = BaseD->isImplicit() &&
Func->getIdentifier()->isMangledOpenMPVariantName();
}
}
if (!S.getLangOpts().OpenMP || !IsImplicitBase)
S.Diag(VD->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(VD) << VD;
} else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
(void)FD;
assert(FD->getMostRecentDecl()->isInlined() &&
"used object requires definition but isn't inline or internal?");
S.Diag(VD->getLocation(), diag::warn_undefined_inline) << VD;
} else {
assert(cast<VarDecl>(VD)->getMostRecentDecl()->isInline() &&
"used var requires definition but isn't inline or internal?");
S.Diag(VD->getLocation(), diag::err_undefined_inline_var) << VD;
}
if (UseLoc.isValid())
S.Diag(UseLoc, diag::note_used_here);
}
S.UndefinedButUsed.clear();
}
void Sema::LoadExternalWeakUndeclaredIdentifiers() {
if (!ExternalSource)
return;
SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
for (auto &WeakID : WeakIDs)
(void)WeakUndeclaredIdentifiers[WeakID.first].insert(WeakID.second);
}
typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
RecordCompleteMap &MNCComplete) {
RecordCompleteMap::iterator Cache = MNCComplete.find(RD);
if (Cache != MNCComplete.end())
return Cache->second;
if (!RD->isCompleteDefinition())
return false;
bool Complete = true;
for (DeclContext::decl_iterator I = RD->decls_begin(),
E = RD->decls_end();
I != E && Complete; ++I) {
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I))
Complete = M->isDefined() || M->isDefaulted() ||
(M->isPure() && !isa<CXXDestructorDecl>(M));
else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
Complete = !F->getTemplatedDecl()->isLateTemplateParsed() &&
F->getTemplatedDecl()->isDefined();
else if (const CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(*I)) {
if (R->isInjectedClassName())
continue;
if (R->hasDefinition())
Complete = MethodsAndNestedClassesComplete(R->getDefinition(),
MNCComplete);
else
Complete = false;
}
}
MNCComplete[RD] = Complete;
return Complete;
}
static bool IsRecordFullyDefined(const CXXRecordDecl *RD,
RecordCompleteMap &RecordsComplete,
RecordCompleteMap &MNCComplete) {
RecordCompleteMap::iterator Cache = RecordsComplete.find(RD);
if (Cache != RecordsComplete.end())
return Cache->second;
bool Complete = MethodsAndNestedClassesComplete(RD, MNCComplete);
for (CXXRecordDecl::friend_iterator I = RD->friend_begin(),
E = RD->friend_end();
I != E && Complete; ++I) {
if (TypeSourceInfo *TSI = (*I)->getFriendType()) {
if (CXXRecordDecl *FriendD = TSI->getType()->getAsCXXRecordDecl())
Complete = MethodsAndNestedClassesComplete(FriendD, MNCComplete);
else
Complete = false;
} else {
if (const FunctionDecl *FD =
dyn_cast<FunctionDecl>((*I)->getFriendDecl()))
Complete = FD->isDefined();
else
Complete = false;
}
}
RecordsComplete[RD] = Complete;
return Complete;
}
void Sema::emitAndClearUnusedLocalTypedefWarnings() {
if (ExternalSource)
ExternalSource->ReadUnusedLocalTypedefNameCandidates(
UnusedLocalTypedefNameCandidates);
for (const TypedefNameDecl *TD : UnusedLocalTypedefNameCandidates) {
if (TD->isReferenced())
continue;
Diag(TD->getLocation(), diag::warn_unused_local_typedef)
<< isa<TypeAliasDecl>(TD) << TD->getDeclName();
}
UnusedLocalTypedefNameCandidates.clear();
}
void Sema::ActOnStartOfTranslationUnit() {
if (getLangOpts().CPlusPlusModules &&
getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit)
HandleStartOfHeaderUnit();
else if (getLangOpts().ModulesTS &&
(getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface ||
getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
SourceLocation StartOfTU =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
ActOnGlobalModuleFragmentDecl(StartOfTU);
ModuleScopes.back().ImplicitGlobalModuleFragment = true;
}
}
void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
if (Kind == TUFragmentKind::Global)
return;
PendingInstantiations.insert(PendingInstantiations.end(),
LateParsedInstantiations.begin(),
LateParsedInstantiations.end());
LateParsedInstantiations.clear();
DefineUsedVTables();
if (ExternalSource) {
SmallVector<PendingImplicitInstantiation, 4> Pending;
ExternalSource->ReadPendingInstantiations(Pending);
for (auto PII : Pending)
if (auto Func = dyn_cast<FunctionDecl>(PII.first))
Func->setInstantiationIsPending(true);
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}
{
llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
PerformPendingInstantiations();
}
emitDeferredDiags();
assert(LateParsedInstantiations.empty() &&
"end of TU template instantiation should not create more "
"late-parsed templates");
for (const auto &Typo : DelayedTypos) {
Typo.second.DiagHandler(TypoCorrection());
}
DelayedTypos.clear();
}
void Sema::ActOnEndOfTranslationUnit() {
assert(DelayedDiagnostics.getCurrentPool() == nullptr
&& "reached end of translation unit with a pool attached?");
if (PP.isCodeCompletionEnabled())
return;
if (TUKind != TU_Prefix) {
DiagnoseUseOfUnimplementedSelectors();
ActOnEndOfTranslationUnitFragment(
!ModuleScopes.empty() && ModuleScopes.back().Module->Kind ==
Module::PrivateModuleFragment
? TUFragmentKind::Private
: TUFragmentKind::Normal);
if (LateTemplateParserCleanup)
LateTemplateParserCleanup(OpaqueParser);
CheckDelayedMemberExceptionSpecs();
} else {
PendingInstantiations.insert(PendingInstantiations.end(),
LateParsedInstantiations.begin(),
LateParsedInstantiations.end());
LateParsedInstantiations.clear();
if (LangOpts.PCHInstantiateTemplates) {
llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
PerformPendingInstantiations();
}
}
DiagnoseUnterminatedPragmaAlignPack();
DiagnoseUnterminatedPragmaAttribute();
DiagnoseUnterminatedOpenMPDeclareTarget();
assert(DelayedOverridingExceptionSpecChecks.empty());
assert(DelayedEquivalentExceptionSpecChecks.empty());
assert(DelayedDllExportClasses.empty());
assert(DelayedDllExportMemberFunctions.empty());
UnusedFileScopedDecls.erase(
std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
UnusedFileScopedDecls.end(),
[this](const DeclaratorDecl *DD) {
return ShouldRemoveFromUnused(this, DD);
}),
UnusedFileScopedDecls.end());
if (TUKind == TU_Prefix) {
if (!PP.isIncrementalProcessingEnabled())
TUScope = nullptr;
return;
}
LoadExternalWeakUndeclaredIdentifiers();
for (const auto &WeakIDs : WeakUndeclaredIdentifiers) {
if (WeakIDs.second.empty())
continue;
Decl *PrevDecl = LookupSingleName(TUScope, WeakIDs.first, SourceLocation(),
LookupOrdinaryName);
if (PrevDecl != nullptr &&
!(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
for (const auto &WI : WeakIDs.second)
Diag(WI.getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'weak'" << ExpectedVariableOrFunction;
else
for (const auto &WI : WeakIDs.second)
Diag(WI.getLocation(), diag::warn_weak_identifier_undeclared)
<< WeakIDs.first;
}
if (LangOpts.CPlusPlus11 &&
!Diags.isIgnored(diag::warn_delegating_ctor_cycle, SourceLocation()))
CheckDelegatingCtorCycles();
if (!Diags.hasErrorOccurred()) {
if (ExternalSource)
ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
checkUndefinedButUsed(*this);
}
bool DiagnosedMissingModuleDeclaration = false;
if (!ModuleScopes.empty() &&
ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment &&
!ModuleScopes.back().ImplicitGlobalModuleFragment) {
Diag(ModuleScopes.back().BeginLoc,
diag::err_module_declaration_missing_after_global_module_introducer);
DiagnosedMissingModuleDeclaration = true;
}
if (TUKind == TU_Module) {
if (getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface &&
(ModuleScopes.empty() ||
!ModuleScopes.back().Module->isModulePurview()) &&
!DiagnosedMissingModuleDeclaration) {
Diag(getSourceManager().getLocForStartOfFile(
getSourceManager().getMainFileID()),
diag::err_module_declaration_missing);
}
if (Module *CurrentModule = PP.getCurrentModule()) {
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
SmallVector<Module *, 2> Stack;
Stack.push_back(CurrentModule);
while (!Stack.empty()) {
Module *Mod = Stack.pop_back_val();
ModMap.resolveExports(Mod, false);
ModMap.resolveUses(Mod, false);
ModMap.resolveConflicts(Mod, false);
Stack.append(Mod->submodule_begin(), Mod->submodule_end());
}
}
emitAndClearUnusedLocalTypedefWarnings();
}
llvm::SmallSet<VarDecl *, 32> Seen;
for (TentativeDefinitionsType::iterator
T = TentativeDefinitions.begin(ExternalSource),
TEnd = TentativeDefinitions.end();
T != TEnd; ++T) {
VarDecl *VD = (*T)->getActingDefinition();
if (!VD || VD->isInvalidDecl() || !Seen.insert(VD).second)
continue;
if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(VD->getType())) {
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
QualType T = Context.getConstantArrayType(ArrayT->getElementType(), One,
nullptr, ArrayType::Normal, 0);
VD->setType(T);
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
diag::err_tentative_def_incomplete_type))
VD->setInvalidDecl();
CheckCompleteVariableDeclaration(VD);
if (!VD->isInvalidDecl())
Consumer.CompleteTentativeDefinition(VD);
}
for (auto D : ExternalDeclarations) {
if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed())
continue;
Consumer.CompleteExternalDeclaration(D);
}
if (!Diags.hasErrorOccurred() && TUKind != TU_Module) {
for (UnusedFileScopedDeclsType::iterator
I = UnusedFileScopedDecls.begin(ExternalSource),
E = UnusedFileScopedDecls.end(); I != E; ++I) {
if (ShouldRemoveFromUnused(this, *I))
continue;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionDecl *DiagD;
if (!FD->hasBody(DiagD))
DiagD = FD;
if (DiagD->isDeleted())
continue; if (DiagD->isReferenced()) {
if (isa<CXXMethodDecl>(DiagD))
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
<< DiagD;
else {
if (FD->getStorageClass() == SC_Static &&
!FD->isInlineSpecified() &&
!SourceMgr.isInMainFile(
SourceMgr.getExpansionLoc(FD->getLocation())))
Diag(DiagD->getLocation(),
diag::warn_unneeded_static_internal_decl)
<< DiagD;
else
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< 0 << DiagD;
}
} else {
if (FD->getDescribedFunctionTemplate())
Diag(DiagD->getLocation(), diag::warn_unused_template)
<< 0 << DiagD;
else
Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
? diag::warn_unused_member_function
: diag::warn_unused_function)
<< DiagD;
}
} else {
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
if (!DiagD)
DiagD = cast<VarDecl>(*I);
if (DiagD->isReferenced()) {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< 1 << DiagD;
} else if (DiagD->getType().isConstQualified()) {
const SourceManager &SM = SourceMgr;
if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
!PP.getLangOpts().IsHeaderFile)
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
<< DiagD;
} else {
if (DiagD->getDescribedVarTemplate())
Diag(DiagD->getLocation(), diag::warn_unused_template)
<< 1 << DiagD;
else
Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD;
}
}
}
emitAndClearUnusedLocalTypedefWarnings();
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
RecordCompleteMap RecordsComplete;
RecordCompleteMap MNCComplete;
for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
E = UnusedPrivateFields.end(); I != E; ++I) {
const NamedDecl *D = *I;
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
if (RD && !RD->isUnion() &&
IsRecordFullyDefined(RD, RecordsComplete, MNCComplete)) {
Diag(D->getLocation(), diag::warn_unused_private_field)
<< D->getDeclName();
}
}
}
if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) {
if (ExternalSource)
ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs);
for (const auto &DeletedFieldInfo : DeleteExprs) {
for (const auto &DeleteExprLoc : DeletedFieldInfo.second) {
AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first,
DeleteExprLoc.second);
}
}
}
assert(ParsingInitForAutoVars.empty() &&
"Didn't unmark var as having its initializer parsed");
if (!PP.isIncrementalProcessingEnabled())
TUScope = nullptr;
}
DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) {
DeclContext *DC = CurContext;
while (true) {
if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC) || isa<CapturedDecl>(DC) ||
isa<RequiresExprBodyDecl>(DC)) {
DC = DC->getParent();
} else if (!AllowLambda && isa<CXXMethodDecl>(DC) &&
cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
DC = DC->getParent()->getParent();
} else break;
}
return DC;
}
FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) {
DeclContext *DC = getFunctionLevelDeclContext(AllowLambda);
return dyn_cast<FunctionDecl>(DC);
}
ObjCMethodDecl *Sema::getCurMethodDecl() {
DeclContext *DC = getFunctionLevelDeclContext();
while (isa<RecordDecl>(DC))
DC = DC->getParent();
return dyn_cast<ObjCMethodDecl>(DC);
}
NamedDecl *Sema::getCurFunctionOrMethodDecl() {
DeclContext *DC = getFunctionLevelDeclContext();
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
return cast<NamedDecl>(DC);
return nullptr;
}
LangAS Sema::getDefaultCXXMethodAddrSpace() const {
if (getLangOpts().OpenCL)
return getASTContext().getDefaultOpenCLPointeeAddrSpace();
return LangAS::Default;
}
void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
if (Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) {
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(
Diags.getCurrentDiagID())) {
case DiagnosticIDs::SFINAE_Report:
break;
case DiagnosticIDs::SFINAE_SubstitutionFailure:
++NumSFINAEErrors;
if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
Diagnostic DiagInfo(&Diags);
(*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
}
Diags.setLastDiagnosticIgnored(true);
Diags.Clear();
return;
case DiagnosticIDs::SFINAE_AccessControl: {
if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11)
break;
SourceLocation Loc = Diags.getCurrentDiagLoc();
++NumSFINAEErrors;
if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
Diagnostic DiagInfo(&Diags);
(*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
}
Diags.setLastDiagnosticIgnored(true);
Diags.Clear();
Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control);
Diags.setLastDiagnosticIgnored(true);
return;
}
case DiagnosticIDs::SFINAE_Suppress:
if (*Info) {
Diagnostic DiagInfo(&Diags);
(*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
}
Diags.setLastDiagnosticIgnored(true);
Diags.Clear();
return;
}
}
Context.setPrintingPolicy(getPrintingPolicy());
if (!Diags.EmitCurrentDiagnostic())
return;
if (!DiagnosticIDs::isBuiltinNote(DiagID))
PrintContextStack();
}
Sema::SemaDiagnosticBuilder
Sema::Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint) {
return Diag(Loc, PD.getDiagID(), DeferHint) << PD;
}
bool Sema::hasUncompilableErrorOccurred() const {
if (getDiagnostics().hasUncompilableErrorOccurred())
return true;
auto *FD = dyn_cast<FunctionDecl>(CurContext);
if (!FD)
return false;
auto Loc = DeviceDeferredDiags.find(FD);
if (Loc == DeviceDeferredDiags.end())
return false;
for (auto PDAt : Loc->second) {
if (DiagnosticIDs::isDefaultMappingAsError(PDAt.second.getDiagID()))
return true;
}
return false;
}
static void emitCallStackNotes(Sema &S, FunctionDecl *FD) {
auto FnIt = S.DeviceKnownEmittedFns.find(FD);
while (FnIt != S.DeviceKnownEmittedFns.end()) {
if (S.Diags.hasFatalErrorOccurred())
return;
DiagnosticBuilder Builder(
S.Diags.Report(FnIt->second.Loc, diag::note_called_by));
Builder << FnIt->second.FD;
FnIt = S.DeviceKnownEmittedFns.find(FnIt->second.FD);
}
}
namespace {
class DeferredDiagnosticsEmitter
: public UsedDeclVisitor<DeferredDiagnosticsEmitter> {
public:
typedef UsedDeclVisitor<DeferredDiagnosticsEmitter> Inherited;
llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> InUsePath;
llvm::SmallVector<CanonicalDeclPtr<FunctionDecl>, 4> UsePath;
llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2];
bool ShouldEmitRootNode;
unsigned InOMPDeviceContext;
DeferredDiagnosticsEmitter(Sema &S)
: Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {}
bool shouldVisitDiscardedStmt() const { return false; }
void VisitOMPTargetDirective(OMPTargetDirective *Node) {
++InOMPDeviceContext;
Inherited::VisitOMPTargetDirective(Node);
--InOMPDeviceContext;
}
void visitUsedDecl(SourceLocation Loc, Decl *D) {
if (isa<VarDecl>(D))
return;
if (auto *FD = dyn_cast<FunctionDecl>(D))
checkFunc(Loc, FD);
else
Inherited::visitUsedDecl(Loc, D);
}
void checkVar(VarDecl *VD) {
assert(VD->isFileVarDecl() &&
"Should only check file-scope variables");
if (auto *Init = VD->getInit()) {
auto DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD);
bool IsDev = DevTy && (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost ||
*DevTy == OMPDeclareTargetDeclAttr::DT_Any);
if (IsDev)
++InOMPDeviceContext;
this->Visit(Init);
if (IsDev)
--InOMPDeviceContext;
}
}
void checkFunc(SourceLocation Loc, FunctionDecl *FD) {
auto &Done = DoneMap[InOMPDeviceContext > 0 ? 1 : 0];
FunctionDecl *Caller = UsePath.empty() ? nullptr : UsePath.back();
if ((!ShouldEmitRootNode && !S.getLangOpts().OpenMP && !Caller) ||
S.shouldIgnoreInHostDeviceCheck(FD) || InUsePath.count(FD))
return;
if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1 &&
(ShouldEmitRootNode || InOMPDeviceContext))
S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
if (Caller)
S.DeviceKnownEmittedFns[FD] = {Caller, Loc};
if (ShouldEmitRootNode || InOMPDeviceContext)
emitDeferredDiags(FD, Caller);
if (!Done.insert(FD).second)
return;
InUsePath.insert(FD);
UsePath.push_back(FD);
if (auto *S = FD->getBody()) {
this->Visit(S);
}
UsePath.pop_back();
InUsePath.erase(FD);
}
void checkRecordedDecl(Decl *D) {
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
ShouldEmitRootNode = S.getEmissionStatus(FD, true) ==
Sema::FunctionEmissionStatus::Emitted;
checkFunc(SourceLocation(), FD);
} else
checkVar(cast<VarDecl>(D));
}
void emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack) {
auto It = S.DeviceDeferredDiags.find(FD);
if (It == S.DeviceDeferredDiags.end())
return;
bool HasWarningOrError = false;
bool FirstDiag = true;
for (PartialDiagnosticAt &PDAt : It->second) {
if (S.Diags.hasFatalErrorOccurred())
return;
const SourceLocation &Loc = PDAt.first;
const PartialDiagnostic &PD = PDAt.second;
HasWarningOrError |=
S.getDiagnostics().getDiagnosticLevel(PD.getDiagID(), Loc) >=
DiagnosticsEngine::Warning;
{
DiagnosticBuilder Builder(S.Diags.Report(Loc, PD.getDiagID()));
PD.Emit(Builder);
}
if (FirstDiag && HasWarningOrError && ShowCallStack) {
emitCallStackNotes(S, FD);
FirstDiag = false;
}
}
}
};
}
void Sema::emitDeferredDiags() {
if (ExternalSource)
ExternalSource->ReadDeclsToCheckForDeferredDiags(
DeclsToCheckForDeferredDiags);
if ((DeviceDeferredDiags.empty() && !LangOpts.OpenMP) ||
DeclsToCheckForDeferredDiags.empty())
return;
DeferredDiagnosticsEmitter DDE(*this);
for (auto D : DeclsToCheckForDeferredDiags)
DDE.checkRecordedDecl(D);
}
Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc,
unsigned DiagID,
FunctionDecl *Fn, Sema &S)
: S(S), Loc(Loc), DiagID(DiagID), Fn(Fn),
ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) {
switch (K) {
case K_Nop:
break;
case K_Immediate:
case K_ImmediateWithCallStack:
ImmediateDiag.emplace(
ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID));
break;
case K_Deferred:
assert(Fn && "Must have a function to attach the deferred diag to.");
auto &Diags = S.DeviceDeferredDiags[Fn];
PartialDiagId.emplace(Diags.size());
Diags.emplace_back(Loc, S.PDiag(DiagID));
break;
}
}
Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D)
: S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn),
ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag),
PartialDiagId(D.PartialDiagId) {
D.ShowCallStack = false;
D.ImmediateDiag.reset();
D.PartialDiagId.reset();
}
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
if (ImmediateDiag) {
bool IsWarningOrError = S.getDiagnostics().getDiagnosticLevel(
DiagID, Loc) >= DiagnosticsEngine::Warning;
ImmediateDiag.reset(); if (IsWarningOrError && ShowCallStack)
emitCallStackNotes(S, Fn);
} else {
assert((!PartialDiagId || ShowCallStack) &&
"Must always show call stack for deferred diags.");
}
}
Sema::SemaDiagnosticBuilder
Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) {
FD = FD ? FD : getCurFunctionDecl();
if (LangOpts.OpenMP)
return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD)
: diagIfOpenMPHostCode(Loc, DiagID, FD);
if (getLangOpts().CUDA)
return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID)
: CUDADiagIfHostCode(Loc, DiagID);
if (getLangOpts().SYCLIsDevice)
return SYCLDiagIfDeviceCode(Loc, DiagID);
return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID,
FD, *this);
}
Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID,
bool DeferHint) {
bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag &&
DiagnosticIDs::isDeferrable(DiagID) &&
(DeferHint || DeferDiags || !IsError);
auto SetIsLastErrorImmediate = [&](bool Flag) {
if (IsError)
IsLastErrorImmediate = Flag;
};
if (!ShouldDefer) {
SetIsLastErrorImmediate(true);
return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc,
DiagID, getCurFunctionDecl(), *this);
}
SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice
? CUDADiagIfDeviceCode(Loc, DiagID)
: CUDADiagIfHostCode(Loc, DiagID);
SetIsLastErrorImmediate(DB.isImmediate());
return DB;
}
void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
if (isUnevaluatedContext() || Ty.isNull())
return;
if (D && LangOpts.SYCLIsDevice) {
llvm::DenseSet<QualType> Visited;
deepTypeCheckForSYCLDevice(Loc, Visited, D);
}
Decl *C = cast<Decl>(getCurLexicalContext());
if (const auto *MD = dyn_cast<CXXMethodDecl>(C)) {
if ((MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) &&
MD->isTrivial())
return;
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(MD))
if (Ctor->isCopyOrMoveConstructor() && Ctor->isTrivial())
return;
}
FunctionDecl *FD = isa<FunctionDecl>(C) ? cast<FunctionDecl>(C)
: dyn_cast_or_null<FunctionDecl>(D);
auto CheckDeviceType = [&](QualType Ty) {
if (Ty->isDependentType())
return;
if (Ty->isBitIntType()) {
if (!Context.getTargetInfo().hasBitIntType()) {
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
if (D)
PD << D;
else
PD << "expression";
targetDiag(Loc, PD, FD)
<< false << 0 << false
<< Ty << Context.getTargetInfo().getTriple().str();
}
return;
}
bool LongDoubleMismatched = false;
if (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128) {
const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(Ty);
if ((&Sem != &llvm::APFloat::PPCDoubleDouble() &&
!Context.getTargetInfo().hasFloat128Type()) ||
(&Sem == &llvm::APFloat::PPCDoubleDouble() &&
!Context.getTargetInfo().hasIbm128Type()))
LongDoubleMismatched = true;
}
if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
(Ty->isFloat128Type() && !Context.getTargetInfo().hasFloat128Type()) ||
(Ty->isIbm128Type() && !Context.getTargetInfo().hasIbm128Type()) ||
(Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
!Context.getTargetInfo().hasInt128Type()) ||
LongDoubleMismatched) {
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
if (D)
PD << D;
else
PD << "expression";
if (targetDiag(Loc, PD, FD)
<< true
<< static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty
<< false << Context.getTargetInfo().getTriple().str()) {
if (D)
D->setInvalidDecl();
}
if (D)
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
}
};
auto CheckType = [&](QualType Ty, bool IsRetTy = false) {
if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice) ||
LangOpts.CUDAIsDevice)
CheckDeviceType(Ty);
QualType UnqualTy = Ty.getCanonicalType().getUnqualifiedType();
const TargetInfo &TI = Context.getTargetInfo();
if (!TI.hasLongDoubleType() && UnqualTy == Context.LongDoubleTy) {
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
if (D)
PD << D;
else
PD << "expression";
if (Diag(Loc, PD, FD)
<< false << 0 << Ty << false
<< Context.getTargetInfo().getTriple().str()) {
if (D)
D->setInvalidDecl();
}
if (D)
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
}
bool IsDouble = UnqualTy == Context.DoubleTy;
bool IsFloat = UnqualTy == Context.FloatTy;
if (IsRetTy && !TI.hasFPReturn() && (IsDouble || IsFloat)) {
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
if (D)
PD << D;
else
PD << "expression";
if (Diag(Loc, PD, FD)
<< false << 0 << Ty << true
<< Context.getTargetInfo().getTriple().str()) {
if (D)
D->setInvalidDecl();
}
if (D)
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
}
};
CheckType(Ty);
if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
for (const auto &ParamTy : FPTy->param_types())
CheckType(ParamTy);
CheckType(FPTy->getReturnType(), true);
}
if (const auto *FNPTy = dyn_cast<FunctionNoProtoType>(Ty))
CheckType(FNPTy->getReturnType(), true);
}
bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
SourceLocation loc = locref;
if (!loc.isMacroID()) return false;
loc = getSourceManager().getExpansionLoc(loc);
SmallString<16> buffer;
if (getPreprocessor().getSpelling(loc, buffer) == name) {
locref = loc;
return true;
}
return false;
}
Scope *Sema::getScopeForContext(DeclContext *Ctx) {
if (!Ctx)
return nullptr;
Ctx = Ctx->getPrimaryContext();
for (Scope *S = getCurScope(); S; S = S->getParent()) {
if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
if (DeclContext *Entity = S->getEntity())
if (Ctx == Entity->getPrimaryContext())
return S;
}
return nullptr;
}
void Sema::PushFunctionScope() {
if (FunctionScopes.empty() && CachedFunctionScope) {
CachedFunctionScope->Clear();
FunctionScopes.push_back(CachedFunctionScope.release());
} else {
FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
if (LangOpts.OpenMP)
pushOpenMPFunctionRegion();
}
void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
BlockScope, Block));
}
LambdaScopeInfo *Sema::PushLambdaScope() {
LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics());
FunctionScopes.push_back(LSI);
return LSI;
}
void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
if (LambdaScopeInfo *const LSI = getCurLambda()) {
LSI->AutoTemplateParameterDepth = Depth;
return;
}
llvm_unreachable(
"Remove assertion if intentionally called in a non-lambda context.");
}
static void checkEscapingByref(VarDecl *VD, Sema &S) {
QualType T = VD->getType();
EnterExpressionEvaluationContext scope(
S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
SourceLocation Loc = VD->getLocation();
Expr *VarRef =
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
ExprResult Result;
auto IE = InitializedEntity::InitializeBlock(Loc, T);
if (S.getLangOpts().CPlusPlus2b) {
auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr,
VK_XValue, FPOptionsOverride());
Result = S.PerformCopyInitialization(IE, SourceLocation(), E);
} else {
Result = S.PerformMoveOrCopyInitialization(
IE, Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible},
VarRef);
}
if (!Result.isInvalid()) {
Result = S.MaybeCreateExprWithCleanups(Result);
Expr *Init = Result.getAs<Expr>();
S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init));
}
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
if (CXXDestructorDecl *DD = RD->getDestructor()) {
auto *FPT = DD->getType()->getAs<FunctionProtoType>();
S.ResolveExceptionSpec(Loc, FPT);
}
}
static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) {
for (const BlockDecl *BD : FSI.Blocks) {
for (const BlockDecl::Capture &BC : BD->captures()) {
VarDecl *VD = BC.getVariable();
if (VD->hasAttr<BlocksAttr>()) {
if (BD->doesNotEscape())
continue;
VD->setEscapingByref();
}
QualType CapType = BC.getVariable()->getType();
if (CapType.hasNonTrivialToPrimitiveDestructCUnion() ||
CapType.hasNonTrivialToPrimitiveCopyCUnion())
S.checkNonTrivialCUnion(BC.getVariable()->getType(),
BD->getCaretLocation(),
Sema::NTCUC_BlockCapture,
Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
}
}
for (VarDecl *VD : FSI.ByrefBlockVars) {
if (!VD->isEscapingByref())
continue;
if (VD->getType()->isStructureOrClassType())
checkEscapingByref(VD, S);
}
}
Sema::PoppedFunctionScopePtr
Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, QualType BlockType) {
assert(!FunctionScopes.empty() && "mismatched push/pop!");
markEscapingByrefs(*FunctionScopes.back(), *this);
PoppedFunctionScopePtr Scope(FunctionScopes.pop_back_val(),
PoppedFunctionScopeDeleter(this));
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope.get());
if (WP && D)
AnalysisWarnings.IssueWarnings(*WP, Scope.get(), D, BlockType);
else
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
Diag(PUD.Loc, PUD.PD);
return Scope;
}
void Sema::PoppedFunctionScopeDeleter::
operator()(sema::FunctionScopeInfo *Scope) const {
if (Scope->isPlainFunction() && !Self->CachedFunctionScope)
Self->CachedFunctionScope.reset(Scope);
else
delete Scope;
}
void Sema::PushCompoundScope(bool IsStmtExpr) {
getCurFunction()->CompoundScopes.push_back(
CompoundScopeInfo(IsStmtExpr, getCurFPFeatures()));
}
void Sema::PopCompoundScope() {
FunctionScopeInfo *CurFunction = getCurFunction();
assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop");
CurFunction->CompoundScopes.pop_back();
}
bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
return getCurFunction()->hasUnrecoverableErrorOccurred();
}
void Sema::setFunctionHasBranchIntoScope() {
if (!FunctionScopes.empty())
FunctionScopes.back()->setHasBranchIntoScope();
}
void Sema::setFunctionHasBranchProtectedScope() {
if (!FunctionScopes.empty())
FunctionScopes.back()->setHasBranchProtectedScope();
}
void Sema::setFunctionHasIndirectGoto() {
if (!FunctionScopes.empty())
FunctionScopes.back()->setHasIndirectGoto();
}
void Sema::setFunctionHasMustTail() {
if (!FunctionScopes.empty())
FunctionScopes.back()->setHasMustTail();
}
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
if (CurBSI && CurBSI->TheDecl &&
!CurBSI->TheDecl->Encloses(CurContext)) {
assert(!CodeSynthesisContexts.empty());
return nullptr;
}
return CurBSI;
}
FunctionScopeInfo *Sema::getEnclosingFunction() const {
if (FunctionScopes.empty())
return nullptr;
for (int e = FunctionScopes.size() - 1; e >= 0; --e) {
if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
continue;
return FunctionScopes[e];
}
return nullptr;
}
LambdaScopeInfo *Sema::getEnclosingLambda() const {
for (auto *Scope : llvm::reverse(FunctionScopes)) {
if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Scope)) {
if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext)) {
assert(!CodeSynthesisContexts.empty());
return nullptr;
}
return LSI;
}
}
return nullptr;
}
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty())
return nullptr;
auto I = FunctionScopes.rbegin();
if (IgnoreNonLambdaCapturingScope) {
auto E = FunctionScopes.rend();
while (I != E && isa<CapturingScopeInfo>(*I) && !isa<LambdaScopeInfo>(*I))
++I;
if (I == E)
return nullptr;
}
auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
if (CurLSI && CurLSI->Lambda &&
!CurLSI->Lambda->Encloses(CurContext)) {
assert(!CodeSynthesisContexts.empty());
return nullptr;
}
return CurLSI;
}
LambdaScopeInfo *Sema::getCurGenericLambda() {
if (LambdaScopeInfo *LSI = getCurLambda()) {
return (LSI->TemplateParams.size() ||
LSI->GLTemplateParameterList) ? LSI : nullptr;
}
return nullptr;
}
void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
SourceMgr.isInSystemHeader(Comment.getBegin()))
return;
RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
if (RC.isAlmostTrailingComment()) {
SourceRange MagicMarkerRange(Comment.getBegin(),
Comment.getBegin().getLocWithOffset(3));
StringRef MagicMarkerText;
switch (RC.getKind()) {
case RawComment::RCK_OrdinaryBCPL:
MagicMarkerText = "///<";
break;
case RawComment::RCK_OrdinaryC:
MagicMarkerText = "/**<";
break;
default:
llvm_unreachable("if this is an almost Doxygen comment, "
"it should be ordinary");
}
Diag(Comment.getBegin(), diag::warn_not_a_doxygen_trailing_member_comment) <<
FixItHint::CreateReplacement(MagicMarkerRange, MagicMarkerText);
}
Context.addComment(RC);
}
ExternalSemaSource::~ExternalSemaSource() {}
char ExternalSemaSource::ID;
void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
void ExternalSemaSource::updateOutOfDateSelector(Selector Sel) { }
void ExternalSemaSource::ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces) {
}
void ExternalSemaSource::ReadUndefinedButUsed(
llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {}
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
UnresolvedSetImpl &OverloadSet) {
ZeroArgCallReturnTy = QualType();
OverloadSet.clear();
const OverloadExpr *Overloads = nullptr;
bool IsMemExpr = false;
if (E.getType() == Context.OverloadTy) {
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
if (FR.HasFormOfMemberPointer)
return false;
Overloads = FR.Expression;
} else if (E.getType() == Context.BoundMemberTy) {
Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens());
IsMemExpr = true;
}
bool Ambiguous = false;
bool IsMV = false;
if (Overloads) {
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
OverloadSet.addDecl(*it);
if (IsMemExpr)
continue;
if (const FunctionDecl *OverloadDecl
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
if (OverloadDecl->getMinRequiredArguments() == 0) {
if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
(!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
OverloadDecl->isCPUSpecificMultiVersion()))) {
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
} else {
ZeroArgCallReturnTy = OverloadDecl->getReturnType();
IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
OverloadDecl->isCPUSpecificMultiVersion();
}
}
}
}
if (!IsMemExpr)
return !ZeroArgCallReturnTy.isNull();
}
if (IsMemExpr && !E.isTypeDependent()) {
Sema::TentativeAnalysisScope Trap(*this);
ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(),
None, SourceLocation());
if (R.isUsable()) {
ZeroArgCallReturnTy = R.get()->getType();
return true;
}
return false;
}
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
if (Fun->getMinRequiredArguments() == 0)
ZeroArgCallReturnTy = Fun->getReturnType();
return true;
}
}
QualType ExprTy = E.getType();
const FunctionType *FunTy = nullptr;
QualType PointeeTy = ExprTy->getPointeeType();
if (!PointeeTy.isNull())
FunTy = PointeeTy->getAs<FunctionType>();
if (!FunTy)
FunTy = ExprTy->getAs<FunctionType>();
if (const FunctionProtoType *FPT =
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
if (FPT->getNumParams() == 0)
ZeroArgCallReturnTy = FunTy->getReturnType();
return true;
}
return false;
}
static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
const SourceLocation FinalNoteLoc) {
unsigned ShownOverloads = 0;
unsigned SuppressedOverloads = 0;
for (UnresolvedSetImpl::iterator It = Overloads.begin(),
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
if (ShownOverloads >= S.Diags.getNumOverloadCandidatesToShow()) {
++SuppressedOverloads;
continue;
}
NamedDecl *Fn = (*It)->getUnderlyingDecl();
if (const auto *FD = Fn->getAsFunction()) {
if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() &&
!FD->getAttr<TargetAttr>()->isDefaultVersion())
continue;
}
S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
++ShownOverloads;
}
S.Diags.overloadCandidatesShown(ShownOverloads);
if (SuppressedOverloads)
S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates)
<< SuppressedOverloads;
}
static void notePlausibleOverloads(Sema &S, SourceLocation Loc,
const UnresolvedSetImpl &Overloads,
bool (*IsPlausibleResult)(QualType)) {
if (!IsPlausibleResult)
return noteOverloads(S, Overloads, Loc);
UnresolvedSet<2> PlausibleOverloads;
for (OverloadExpr::decls_iterator It = Overloads.begin(),
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It);
QualType OverloadResultTy = OverloadDecl->getReturnType();
if (IsPlausibleResult(OverloadResultTy))
PlausibleOverloads.addDecl(It.getDecl());
}
noteOverloads(S, PlausibleOverloads, Loc);
}
static bool IsCallableWithAppend(Expr *E) {
E = E->IgnoreImplicit();
return (!isa<CStyleCastExpr>(E) &&
!isa<UnaryOperator>(E) &&
!isa<BinaryOperator>(E) &&
!isa<CXXOperatorCallExpr>(E));
}
static bool IsCPUDispatchCPUSpecificMultiVersion(const Expr *E) {
if (const auto *UO = dyn_cast<UnaryOperator>(E))
E = UO->getSubExpr();
if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
if (ULE->getNumDecls() == 0)
return false;
const NamedDecl *ND = *ULE->decls_begin();
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion();
}
return false;
}
bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
bool ForceComplain,
bool (*IsPlausibleResult)(QualType)) {
SourceLocation Loc = E.get()->getExprLoc();
SourceRange Range = E.get()->getSourceRange();
UnresolvedSet<4> Overloads;
if (!isSFINAEContext()) {
QualType ZeroArgCallTy;
if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
!ZeroArgCallTy.isNull() &&
(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
Diag(Loc, PD) << 1 << IsMV << Range
<< (IsCallableWithAppend(E.get())
? FixItHint::CreateInsertion(ParenInsertionLoc,
"()")
: FixItHint());
if (!IsMV)
notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
Range.getEnd().getLocWithOffset(1));
return true;
}
}
if (!ForceComplain) return false;
bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
Diag(Loc, PD) << 0 << IsMV << Range;
if (!IsMV)
notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
E = ExprError();
return true;
}
IdentifierInfo *Sema::getSuperIdentifier() const {
if (!Ident_super)
Ident_super = &Context.Idents.get("super");
return Ident_super;
}
IdentifierInfo *Sema::getFloat128Identifier() const {
if (!Ident___float128)
Ident___float128 = &Context.Idents.get("__float128");
return Ident___float128;
}
void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
CapturedRegionKind K,
unsigned OpenMPCaptureLevel) {
auto *CSI = new CapturedRegionScopeInfo(
getDiagnostics(), S, CD, RD, CD->getContextParam(), K,
(getLangOpts().OpenMP && K == CR_OpenMP) ? getOpenMPNestingLevel() : 0,
OpenMPCaptureLevel);
CSI->ReturnType = Context.VoidTy;
FunctionScopes.push_back(CSI);
}
CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
if (FunctionScopes.empty())
return nullptr;
return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
}
const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
Sema::getMismatchingDeleteExpressions() const {
return DeleteExprs;
}
Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S)
: S(S), OldFPFeaturesState(S.CurFPFeatures),
OldOverrides(S.FpPragmaStack.CurrentValue),
OldEvalMethod(S.PP.getCurrentFPEvalMethod()),
OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {}
Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
S.CurFPFeatures = OldFPFeaturesState;
S.FpPragmaStack.CurrentValue = OldOverrides;
S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
}