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.cpp232
1 files changed, 148 insertions, 84 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 4e57e5ef81c6f..d57473c5616f4 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -19,6 +19,7 @@
#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/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -31,12 +32,12 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
-#include "clang/Sema/PrettyDeclStackTrace.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 "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -51,8 +52,8 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
- // Our printing policy is copied over the ASTContext printing policy whenever
- // a diagnostic is emitted, so recompute it.
+ // In diagnostics, we print _Bool as bool if the latter is defined as the
+ // former.
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
@@ -130,16 +131,19 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
- CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr),
- NSValueDecl(nullptr), NSStringDecl(nullptr),
- StringWithUTF8StringMethod(nullptr),
+ StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
+ MSVCGuidDecl(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), AccessCheckingSFINAE(false),
- InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
- ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
- DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
+ TUKind(TUKind), NumSFINAEErrors(0),
+ FullyCheckedComparisonCategories(
+ static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
+ 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) {
TUScope = nullptr;
@@ -159,9 +163,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExprEvalContexts.emplace_back(
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
- nullptr, false);
+ nullptr, ExpressionEvaluationContextRecord::EK_Other);
- FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+ PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
// Initilization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
@@ -331,11 +335,11 @@ void Sema::Initialize() {
Sema::~Sema() {
if (VisContext) FreeVisContext();
+
// Kill all the active scopes.
- for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
- delete FunctionScopes[I];
- if (FunctionScopes.size() == 1)
- delete FunctionScopes[0];
+ for (sema::FunctionScopeInfo *FSI : FunctionScopes)
+ if (FSI != PreallocatedFunctionScope.get())
+ delete FSI;
// Tell the SemaConsumer to forget about us; we're going out of scope.
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
@@ -391,7 +395,7 @@ ASTMutationListener *Sema::getASTMutationListener() const {
return getASTConsumer().GetASTMutationListener();
}
-///\brief Registers an external source. If an external source already exists,
+///Registers an external source. If an external source already exists,
/// creates a multiplex external source and appends to it.
///
///\param[in] E - A non-null external sema source.
@@ -412,7 +416,7 @@ void Sema::addExternalSource(ExternalSemaSource *E) {
}
}
-/// \brief Print out statistics about the semantic analysis.
+/// Print out statistics about the semantic analysis.
void Sema::PrintStats() const {
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
@@ -477,6 +481,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_ToVoid:
+ case CK_NonAtomicToAtomic:
break;
}
}
@@ -532,7 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
llvm_unreachable("unknown scalar type kind");
}
-/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+/// Used to prune the decls of Sema's UnusedFileScopedDecls vector.
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
@@ -641,6 +646,8 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(FD) &&
!FD->getMostRecentDecl()->isInlined())
continue;
+ if (FD->getBuiltinID())
+ continue;
} else {
auto *VD = cast<VarDecl>(ND);
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
@@ -649,6 +656,11 @@ void Sema::getUndefinedButUsed(
!isExternalWithNoLinkageType(VD) &&
!VD->getMostRecentDecl()->isInline())
continue;
+
+ // Skip VarDecls that lack formal definitions but which we know are in
+ // fact defined somewhere.
+ if (VD->isKnownToBeDefined())
+ continue;
}
Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
@@ -720,7 +732,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
-/// \brief Returns true, if all methods and nested classes of the given
+/// Returns true, if all methods and nested classes of the given
/// CXXRecordDecl are defined in this translation unit.
///
/// Should only be called from ActOnEndOfTranslationUnit so that all
@@ -760,7 +772,7 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
return Complete;
}
-/// \brief Returns true, if the given CXXRecordDecl is fully defined in this
+/// Returns true, if the given CXXRecordDecl is fully defined in this
/// translation unit, i.e. all methods are defined or pure virtual and all
/// friends, friend functions and nested classes are fully defined in this
/// translation unit.
@@ -849,6 +861,20 @@ void Sema::ActOnEndOfTranslationUnit() {
if (PP.isCodeCompletionEnabled())
return;
+ // Transfer late parsed template instantiations over to the pending template
+ // instantiation list. During normal compliation, the late template parser
+ // will be installed and instantiating these templates will succeed.
+ //
+ // If we are building a TU prefix for serialization, it is also safe to
+ // transfer these over, even though they are not parsed. The end of the TU
+ // should be outside of any eager template instantiation scope, so when this
+ // AST is deserialized, these templates will not be parsed until the end of
+ // the combined TU.
+ PendingInstantiations.insert(PendingInstantiations.end(),
+ LateParsedInstantiations.begin(),
+ LateParsedInstantiations.end());
+ LateParsedInstantiations.clear();
+
// Complete translation units and modules define vtables and perform implicit
// instantiations. PCH files do not.
if (TUKind != TU_Prefix) {
@@ -878,8 +904,13 @@ void Sema::ActOnEndOfTranslationUnit() {
PendingInstantiations.insert(PendingInstantiations.begin(),
Pending.begin(), Pending.end());
}
+
PerformPendingInstantiations();
+ assert(LateParsedInstantiations.empty() &&
+ "end of TU template instantiation should not create more "
+ "late-parsed templates");
+
if (LateTemplateParserCleanup)
LateTemplateParserCleanup(OpaqueParser);
@@ -980,11 +1011,6 @@ void Sema::ActOnEndOfTranslationUnit() {
// Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
// modules when they are built, not every time they are used.
emitAndClearUnusedLocalTypedefWarnings();
-
- // Modules don't need any of the checking below.
- if (!PP.isIncrementalProcessingEnabled())
- TUScope = nullptr;
- return;
}
// C99 6.9.2p2:
@@ -1002,8 +1028,7 @@ void Sema::ActOnEndOfTranslationUnit() {
for (TentativeDefinitionsType::iterator
T = TentativeDefinitions.begin(ExternalSource),
TEnd = TentativeDefinitions.end();
- T != TEnd; ++T)
- {
+ T != TEnd; ++T) {
VarDecl *VD = (*T)->getActingDefinition();
// If the tentative definition was completed, getActingDefinition() returns
@@ -1030,12 +1055,13 @@ void Sema::ActOnEndOfTranslationUnit() {
// Notify the consumer that we've completed a tentative definition.
if (!VD->isInvalidDecl())
Consumer.CompleteTentativeDefinition(VD);
-
}
// If there were errors, disable 'unused' warnings since they will mostly be
- // noise.
- if (!Diags.hasErrorOccurred()) {
+ // noise. Don't warn for a use from a module: either we should warn on all
+ // file-scope declarations in modules or not at all, but whether the
+ // declaration is used is immaterial.
+ if (!Diags.hasErrorOccurred() && TUKind != TU_Module) {
// Output warning for unused file scoped decls.
for (UnusedFileScopedDeclsType::iterator
I = UnusedFileScopedDecls.begin(ExternalSource),
@@ -1103,6 +1129,8 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
+ // FIXME: Load additional unused private field candidates from the external
+ // source.
RecordCompleteMap RecordsComplete;
RecordCompleteMap MNCComplete;
for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
@@ -1264,7 +1292,8 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
}
}
- // Set up the context's printing policy based on our current state.
+ // Copy the diagnostic printing policy over the ASTContext printing policy.
+ // TODO: Stop doing that. See: https://reviews.llvm.org/D45093#1090292
Context.setPrintingPolicy(getPrintingPolicy());
// Emit the diagnostic.
@@ -1287,7 +1316,7 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
return Builder;
}
-/// \brief Looks through the macro-expansion chain for the given
+/// Looks through the macro-expansion chain for the given
/// location, looking for a macro expansion with the given name.
/// If one is found, returns true and sets the location to that
/// expansion loc.
@@ -1308,7 +1337,7 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
return false;
}
-/// \brief Determines the active Scope associated with the given declaration
+/// Determines the active Scope associated with the given declaration
/// context.
///
/// This routine maps a declaration context to the active Scope object that
@@ -1337,19 +1366,15 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
return nullptr;
}
-/// \brief Enter a new function scope
+/// Enter a new function scope
void Sema::PushFunctionScope() {
- if (FunctionScopes.size() == 1) {
- // Use the "top" function scope rather than having to allocate
- // memory for a new scope.
- FunctionScopes.back()->Clear();
- FunctionScopes.push_back(FunctionScopes.back());
- if (LangOpts.OpenMP)
- pushOpenMPFunctionRegion();
- return;
+ if (FunctionScopes.empty()) {
+ // Use PreallocatedFunctionScope to avoid allocating memory when possible.
+ PreallocatedFunctionScope->Clear();
+ FunctionScopes.push_back(PreallocatedFunctionScope.get());
+ } else {
+ FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
}
-
- FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
if (LangOpts.OpenMP)
pushOpenMPFunctionRegion();
}
@@ -1369,15 +1394,15 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
if (LambdaScopeInfo *const LSI = getCurLambda()) {
LSI->AutoTemplateParameterDepth = Depth;
return;
- }
- llvm_unreachable(
+ }
+ llvm_unreachable(
"Remove assertion if intentionally called in a non-lambda context.");
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope);
@@ -1389,12 +1414,13 @@ void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
Diag(PUD.Loc, PUD.PD);
- if (FunctionScopes.back() != Scope)
+ // Delete the scope unless its our preallocated scope.
+ if (Scope != PreallocatedFunctionScope.get())
delete Scope;
}
-void Sema::PushCompoundScope() {
- getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo());
+void Sema::PushCompoundScope(bool IsStmtExpr) {
+ getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo(IsStmtExpr));
}
void Sema::PopCompoundScope() {
@@ -1404,12 +1430,27 @@ void Sema::PopCompoundScope() {
CurFunction->CompoundScopes.pop_back();
}
-/// \brief Determine whether any errors occurred within this function/method/
+/// Determine whether any errors occurred within this function/method/
/// block.
bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
return getCurFunction()->ErrorTrap.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();
+}
+
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
@@ -1425,6 +1466,18 @@ BlockScopeInfo *Sema::getCurBlock() {
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::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty())
return nullptr;
@@ -1462,8 +1515,7 @@ void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
SourceMgr.isInSystemHeader(Comment.getBegin()))
return;
- RawComment RC(SourceMgr, Comment, false,
- LangOpts.CommentOpts.ParseAllComments);
+ RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
if (RC.isAlmostTrailingComment()) {
SourceRange MagicMarkerRange(Comment.getBegin(),
Comment.getBegin().getLocWithOffset(3));
@@ -1501,25 +1553,7 @@ void ExternalSemaSource::ReadUndefinedButUsed(
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
-void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
- SourceLocation Loc = this->Loc;
- if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
- if (Loc.isValid()) {
- Loc.print(OS, S.getSourceManager());
- OS << ": ";
- }
- OS << Message;
-
- if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
- OS << " '";
- ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), true);
- OS << "'";
- }
-
- OS << '\n';
-}
-
-/// \brief Figure out if an expression could be turned into a call.
+/// Figure out if an expression could be turned into a call.
///
/// Use this when trying to recover from an error where the programmer may have
/// written just the name of a function instead of actually calling it.
@@ -1551,6 +1585,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
}
bool Ambiguous = false;
+ bool IsMV = false;
if (Overloads) {
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
@@ -1564,11 +1599,16 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
if (const FunctionDecl *OverloadDecl
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
if (OverloadDecl->getMinRequiredArguments() == 0) {
- if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) {
+ if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
+ (!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion()))) {
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
- } else
+ } else {
ZeroArgCallReturnTy = OverloadDecl->getReturnType();
+ IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
+ OverloadDecl->isCPUSpecificMultiVersion();
+ }
}
}
}
@@ -1621,7 +1661,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
return false;
}
-/// \brief Give notes for a set of overloads.
+/// Give notes for a set of overloads.
///
/// A companion to tryExprAsCall. In cases when the name that the programmer
/// wrote was an overloaded function, we may be able to make some guesses about
@@ -1647,6 +1687,12 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
}
NamedDecl *Fn = (*It)->getUnderlyingDecl();
+ // Don't print overloads for non-default multiversioned functions.
+ 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;
}
@@ -1685,6 +1731,21 @@ static bool IsCallableWithAppend(Expr *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)) {
@@ -1701,12 +1762,13 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
- Diag(Loc, PD)
- << /*zero-arg*/ 1 << Range
- << (IsCallableWithAppend(E.get())
- ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
- : FixItHint());
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
+ << (IsCallableWithAppend(E.get())
+ ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
+ : FixItHint());
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
@@ -1717,8 +1779,10 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
if (!ForceComplain) return false;
- Diag(Loc, PD) << /*not zero-arg*/ 0 << Range;
- notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+ bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+ Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range;
+ if (!IsMV)
+ notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
E = ExprError();
return true;
}