summaryrefslogtreecommitdiff
path: root/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r--lib/Sema/Sema.cpp135
1 files changed, 120 insertions, 15 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 49f3decc11517..9fa39968625a6 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -152,7 +152,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = nullptr;
- if (getLangOpts().ObjC1)
+ if (getLangOpts().ObjC)
NSAPIObj.reset(new NSAPI(Context));
if (getLangOpts().CPlusPlus)
@@ -167,7 +167,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
- // Initilization of data sharing attributes stack for OpenMP
+ // Initialization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
@@ -214,7 +214,7 @@ void Sema::Initialize() {
// Initialize predefined Objective-C types:
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
// If 'SEL' does not yet refer to any declarations, make it refer to the
// predefined 'SEL'.
DeclarationName SEL = &Context.Idents.get("SEL");
@@ -320,6 +320,10 @@ void Sema::Initialize() {
#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
setOpenCLExtensionForType(Context.Id, Ext);
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ addImplicitTypedef(#ExtType, Context.Id##Ty); \
+ setOpenCLExtensionForType(Context.Id##Ty, #Ext);
+#include "clang/Basic/OpenCLExtensionTypes.def"
};
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
@@ -441,7 +445,7 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
- E->getLocStart()))
+ E->getBeginLoc()))
return;
// nullptr only exists from C++11 on, so don't warn on its absence earlier.
if (!getLangOpts().CPlusPlus11)
@@ -454,13 +458,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
// If it is a macro from system header, and if the macro name is not "NULL",
// do not warn.
- SourceLocation MaybeMacroLoc = E->getLocStart();
+ SourceLocation MaybeMacroLoc = E->getBeginLoc();
if (Diags.getSuppressSystemWarnings() &&
SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
!findMacroSpelling(MaybeMacroLoc, "NULL"))
return;
- Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant)
+ Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant)
<< FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
}
@@ -488,7 +492,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
#endif
- diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart());
+ diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
diagnoseZeroToNullptrConversion(Kind, E);
QualType ExprTy = Context.getCanonicalType(E->getType());
@@ -533,6 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
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");
}
@@ -644,7 +649,8 @@ void Sema::getUndefinedButUsed(
continue;
if (FD->isExternallyVisible() &&
!isExternalWithNoLinkageType(FD) &&
- !FD->getMostRecentDecl()->isInlined())
+ !FD->getMostRecentDecl()->isInlined() &&
+ !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (FD->getBuiltinID())
continue;
@@ -654,7 +660,8 @@ void Sema::getUndefinedButUsed(
continue;
if (VD->isExternallyVisible() &&
!isExternalWithNoLinkageType(VD) &&
- !VD->getMostRecentDecl()->isInline())
+ !VD->getMostRecentDecl()->isInline() &&
+ !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
// Skip VarDecls that lack formal definitions but which we know are in
@@ -827,7 +834,9 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() {
/// is parsed. Note that the ASTContext may have already injected some
/// declarations.
void Sema::ActOnStartOfTranslationUnit() {
- if (getLangOpts().ModulesTS) {
+ if (getLangOpts().ModulesTS &&
+ (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface ||
+ getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
SourceLocation StartOfTU =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
@@ -922,10 +931,9 @@ void Sema::ActOnEndOfTranslationUnit() {
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
- // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to
- // write out the lists to the AST file (if any).
+ assert(DelayedOverridingExceptionSpecChecks.empty());
+ assert(DelayedEquivalentExceptionSpecChecks.empty());
assert(DelayedDefaultedMemberExceptionSpecs.empty());
- assert(DelayedExceptionSpecChecks.empty());
// All dllexport classes should have been processed already.
assert(DelayedDllExportClasses.empty());
@@ -978,7 +986,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// module declaration by now.
if (getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface &&
- ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) {
+ (ModuleScopes.empty() ||
+ ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)) {
// FIXME: Make a better guess as to where to put the module declaration.
Diag(getSourceManager().getLocForStartOfFile(
getSourceManager().getMainFileID()),
@@ -1399,9 +1408,69 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
"Remove assertion if intentionally called in a non-lambda context.");
}
+// Check that the type of the VarDecl has an accessible copy constructor and
+// resolve its destructor's exception spefication.
+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 = S.PerformMoveOrCopyInitialization(
+ InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
+ VarRef, /*AllowNRVO=*/true);
+ if (!Result.isInvalid()) {
+ Result = S.MaybeCreateExprWithCleanups(Result);
+ Expr *Init = Result.getAs<Expr>();
+ S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init));
+ }
+
+ // The destructor's exception spefication is needed when IRGen generates
+ // block copy/destroy functions. Resolve it here.
+ 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) {
+ // Set the EscapingByref flag of __block variables captured by
+ // escaping blocks.
+ for (const BlockDecl *BD : FSI.Blocks) {
+ if (BD->doesNotEscape())
+ continue;
+ for (const BlockDecl::Capture &BC : BD->captures()) {
+ VarDecl *VD = BC.getVariable();
+ if (VD->hasAttr<BlocksAttr>())
+ VD->setEscapingByref();
+ }
+ }
+
+ for (VarDecl *VD : FSI.ByrefBlockVars) {
+ // __block variables might require us to capture a copy-initializer.
+ if (!VD->isEscapingByref())
+ continue;
+ // It's currently invalid to ever have a __block variable with an
+ // array type; should we diagnose that here?
+ // Regardless, we don't want to ignore array nesting when
+ // constructing this copy.
+ if (VD->getType()->isStructureOrClassType())
+ checkEscapingByref(VD, S);
+ }
+}
+
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+
+ // This function shouldn't be called after popping the current function scope.
+ // markEscapingByrefs calls PerformMoveOrCopyInitialization, which can call
+ // PushFunctionScope, which can cause clearing out PreallocatedFunctionScope
+ // when FunctionScopes is empty.
+ markEscapingByrefs(*FunctionScopes.back(), *this);
+
FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
@@ -1851,6 +1920,34 @@ void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
}
+std::string Sema::getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD) {
+ if (!OpenCLDeclExtMap.empty())
+ return getOpenCLExtensionsFromExtMap(FD, OpenCLDeclExtMap);
+
+ return "";
+}
+
+std::string Sema::getOpenCLExtensionsFromTypeExtMap(FunctionType *FT) {
+ if (!OpenCLTypeExtMap.empty())
+ return getOpenCLExtensionsFromExtMap(FT, OpenCLTypeExtMap);
+
+ return "";
+}
+
+template <typename T, typename MapT>
+std::string Sema::getOpenCLExtensionsFromExtMap(T *FDT, MapT &Map) {
+ std::string ExtensionNames = "";
+ auto Loc = Map.find(FDT);
+
+ for (auto const& I : Loc->second) {
+ ExtensionNames += I;
+ ExtensionNames += " ";
+ }
+ ExtensionNames.pop_back();
+
+ return ExtensionNames;
+}
+
bool Sema::isOpenCLDisabledDecl(Decl *FD) {
auto Loc = OpenCLDeclExtMap.find(FD);
if (Loc == OpenCLDeclExtMap.end())
@@ -1889,6 +1986,14 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
Decl = TagT->getDecl();
auto Loc = DS.getTypeSpecTypeLoc();
+
+ // Check extensions for vector types.
+ // e.g. double4 is not allowed when cl_khr_fp64 is absent.
+ if (QT->isExtVectorType()) {
+ auto TypePtr = QT->castAs<ExtVectorType>()->getElementType().getTypePtr();
+ return checkOpenCLDisabledTypeOrDecl(TypePtr, Loc, QT, OpenCLTypeExtMap);
+ }
+
if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
return true;
@@ -1899,6 +2004,6 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) {
IdentifierInfo *FnName = D.getIdentifier();
- return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName,
+ return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName,
OpenCLDeclExtMap, 1, D.getSourceRange());
}