2006-11-10 12:58:55 +08:00
|
|
|
//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2006-11-10 12:58:55 +08:00
|
|
|
// This file implements the actions class which performs semantic analysis and
|
|
|
|
// builds an AST out of a parse stream.
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2020-02-26 23:57:39 +08:00
|
|
|
#include "UsedDeclVisitor.h"
|
2006-11-10 14:20:45 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-02-10 06:26:47 +08:00
|
|
|
#include "clang/AST/ASTDiagnostic.h"
|
2021-01-29 16:42:20 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
2010-08-25 15:42:41 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2012-06-06 16:32:04 +08:00
|
|
|
#include "clang/AST/DeclFriend.h"
|
2008-08-11 13:35:13 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-08-11 12:54:23 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2011-05-05 06:10:40 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2018-03-23 08:07:18 +08:00
|
|
|
#include "clang/AST/PrettyDeclStackTrace.h"
|
2011-02-17 15:39:24 +08:00
|
|
|
#include "clang/AST/StmtCXX.h"
|
2014-05-11 00:31:55 +08:00
|
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
2009-08-27 06:33:56 +08:00
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
2020-02-28 03:01:58 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
Improve behavior in the case of stack exhaustion.
Summary:
Clang performs various recursive operations (such as template instantiation),
and may use non-trivial amounts of stack space in each recursive step (for
instance, due to recursive AST walks). While we try to keep the stack space
used by such steps to a minimum and we have explicit limits on the number of
such steps we perform, it's impractical to guarantee that we won't blow out the
stack on deeply recursive template instantiations on complex ASTs, even with
only a moderately high instantiation depth limit.
The user experience in these cases is generally terrible: we crash with
no hint of what went wrong. Under this patch, we attempt to do better:
* Detect when the stack is nearly exhausted, and produce a warning with a
nice template instantiation backtrace, telling the user that we might
run slowly or crash.
* For cases where we're forced to trigger recursive template
instantiation in arbitrarily-deeply-nested contexts, check whether
we're nearly out of stack space and allocate a new stack (by spawning
a new thread) after producing the warning.
Reviewers: rnk, aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66361
llvm-svn: 369940
2019-08-27 02:18:07 +08:00
|
|
|
#include "clang/Basic/Stack.h"
|
2009-04-30 14:18:40 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "clang/Sema/CXXFieldCollector.h"
|
|
|
|
#include "clang/Sema/DelayedDiagnostic.h"
|
|
|
|
#include "clang/Sema/ExternalSemaSource.h"
|
2016-08-12 06:25:46 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/MultiplexExternalSemaSource.h"
|
|
|
|
#include "clang/Sema/ObjCMethodList.h"
|
|
|
|
#include "clang/Sema/Scope.h"
|
|
|
|
#include "clang/Sema/ScopeInfo.h"
|
|
|
|
#include "clang/Sema/SemaConsumer.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/TemplateDeduction.h"
|
2018-02-10 22:04:45 +08:00
|
|
|
#include "clang/Sema/TemplateInstCallback.h"
|
[Sema] Emit diagnostics for uncorrected delayed typos at the end of TU
Summary:
Instead of asserting all typos are corrected in the sema destructor.
The sema destructor is not run in the common case of running the compiler
with the -disable-free cc1 flag (which is the default in the driver).
Having this assertion led to crashes in libclang and clangd, which are not
reproducible when running the compiler.
Asserting at the end of the TU could be an option, but finding all
missing typo correction cases is hard and having worse diagnostics instead
of a failing assertion is a better trade-off.
For more discussion on this, see:
https://lists.llvm.org/pipermail/cfe-dev/2019-July/062872.html
Reviewers: sammccall, rsmith
Reviewed By: rsmith
Subscribers: usaxena95, dgoldman, jkorous, vsapsai, rnk, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64799
llvm-svn: 374152
2019-10-09 18:00:05 +08:00
|
|
|
#include "clang/Sema/TypoCorrection.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2020-07-20 22:41:44 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2019-03-30 16:42:48 +08:00
|
|
|
#include "llvm/Support/TimeProfiler.h"
|
|
|
|
|
2006-08-18 13:17:52 +08:00
|
|
|
using namespace clang;
|
2010-08-25 16:40:02 +08:00
|
|
|
using namespace sema;
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
|
2014-05-03 11:45:55 +08:00
|
|
|
SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
|
|
|
|
return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
|
|
|
|
|
2020-01-22 08:03:05 +08:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2012-01-17 10:15:51 +08:00
|
|
|
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
|
|
|
|
const Preprocessor &PP) {
|
2011-09-28 07:30:47 +08:00
|
|
|
PrintingPolicy Policy = Context.getPrintingPolicy();
|
2018-05-15 02:41:44 +08:00
|
|
|
// In diagnostics, we print _Bool as bool if the latter is defined as the
|
|
|
|
// former.
|
2012-03-11 15:00:24 +08:00
|
|
|
Policy.Bool = Context.getLangOpts().Bool;
|
2011-09-28 07:30:47 +08:00
|
|
|
if (!Policy.Bool) {
|
2016-05-19 09:39:10 +08:00
|
|
|
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
|
2013-01-20 09:04:14 +08:00
|
|
|
Policy.Bool = BoolMacro->isObjectLike() &&
|
2016-05-19 09:39:10 +08:00
|
|
|
BoolMacro->getNumTokens() == 1 &&
|
|
|
|
BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
|
2011-09-28 07:30:47 +08:00
|
|
|
}
|
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-09-28 07:30:47 +08:00
|
|
|
return Policy;
|
|
|
|
}
|
|
|
|
|
2010-08-26 02:07:12 +08:00
|
|
|
void Sema::ActOnTranslationUnitScope(Scope *S) {
|
2007-11-01 02:42:27 +08:00
|
|
|
TUScope = S;
|
2008-12-12 00:49:14 +08:00
|
|
|
PushDeclContext(S, Context.getTranslationUnitDecl());
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
2007-10-11 05:53:07 +08:00
|
|
|
|
2017-07-28 22:41:21 +08:00
|
|
|
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; }
|
|
|
|
|
|
|
|
virtual 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()) {
|
2019-03-30 16:42:48 +08:00
|
|
|
if (llvm::timeTraceProfilerEnabled()) {
|
|
|
|
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc));
|
|
|
|
llvm::timeTraceProfilerBegin(
|
|
|
|
"Source", FE != nullptr ? FE->getName() : StringRef("<unknown>"));
|
|
|
|
}
|
|
|
|
|
2017-07-28 22:41:21 +08:00
|
|
|
IncludeStack.push_back(IncludeLoc);
|
2021-01-08 06:16:33 +08:00
|
|
|
S->DiagnoseNonDefaultPragmaAlignPack(
|
|
|
|
Sema::PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude,
|
|
|
|
IncludeLoc);
|
2017-07-28 22:41:21 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ExitFile:
|
2019-03-30 16:42:48 +08:00
|
|
|
if (!IncludeStack.empty()) {
|
|
|
|
if (llvm::timeTraceProfilerEnabled())
|
|
|
|
llvm::timeTraceProfilerEnd();
|
|
|
|
|
2021-01-08 06:16:33 +08:00
|
|
|
S->DiagnoseNonDefaultPragmaAlignPack(
|
|
|
|
Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit,
|
2017-07-28 22:41:21 +08:00
|
|
|
IncludeStack.pop_back_val());
|
2019-03-30 16:42:48 +08:00
|
|
|
}
|
2017-07-28 22:41:21 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace sema
|
|
|
|
} // end namespace clang
|
|
|
|
|
2020-01-24 23:17:34 +08:00
|
|
|
const unsigned Sema::MaxAlignmentExponent;
|
|
|
|
const unsigned Sema::MaximumAlignment;
|
|
|
|
|
2009-04-15 00:27:31 +08:00
|
|
|
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
2017-04-18 22:33:39 +08:00
|
|
|
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
|
|
|
|
: ExternalSource(nullptr), isMultiplexExternalSource(false),
|
2020-04-16 23:45:26 +08:00
|
|
|
CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
|
2017-04-18 22:33:39 +08:00
|
|
|
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
|
|
|
|
SourceMgr(PP.getSourceManager()), CollectStats(false),
|
|
|
|
CodeCompleter(CodeCompleter), CurContext(nullptr),
|
|
|
|
OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
|
|
|
|
MSPointerToMemberRepresentationMethod(
|
|
|
|
LangOpts.getMSPointerToMemberRepresentationMethod()),
|
2021-01-13 22:49:19 +08:00
|
|
|
VtorDispStack(LangOpts.getVtorDispMode()),
|
|
|
|
AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
|
2017-04-18 22:33:39 +08:00
|
|
|
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
|
2020-08-17 07:36:10 +08:00
|
|
|
CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()),
|
|
|
|
CurInitSeg(nullptr), VisContext(nullptr),
|
|
|
|
PragmaAttributeCurrentTargetDecl(nullptr),
|
2017-04-18 22:33:39 +08:00
|
|
|
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
|
|
|
|
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
|
|
|
|
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
|
2018-07-15 02:21:44 +08:00
|
|
|
StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr),
|
|
|
|
MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr),
|
|
|
|
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
|
2017-04-18 22:33:39 +08:00
|
|
|
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
|
|
|
|
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
|
|
|
|
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
|
[C++2a] Implement operator<=> CodeGen and ExprConstant
Summary:
This patch tackles long hanging fruit for the builtin operator<=> expressions. It is currently needs some cleanup before landing, but I want to get some initial feedback.
The main changes are:
* Lookup, build, and store the required standard library types and expressions in `ASTContext`. By storing them in ASTContext we don't need to store (and duplicate) the required expressions in the BinaryOperator AST nodes.
* Implement [expr.spaceship] checking, including diagnosing narrowing conversions.
* Implement `ExprConstant` for builtin spaceship operators.
* Implement builitin operator<=> support in `CodeGenAgg`. Initially I emitted the required comparisons using `ScalarExprEmitter::VisitBinaryOperator`, but this caused the operand expressions to be emitted once for every required cmp.
* Implement [builtin.over] with modifications to support the intent of P0946R0. See the note on `BuiltinOperatorOverloadBuilder::addThreeWayArithmeticOverloads` for more information about the workaround.
Reviewers: rsmith, aaron.ballman, majnemer, rnk, compnerd, rjmccall
Reviewed By: rjmccall
Subscribers: rjmccall, rsmith, aaron.ballman, junbuml, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D45476
llvm-svn: 331677
2018-05-08 05:07:10 +08:00
|
|
|
TUKind(TUKind), NumSFINAEErrors(0),
|
|
|
|
FullyCheckedComparisonCategories(
|
|
|
|
static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
|
2020-01-22 08:50:12 +08:00
|
|
|
SatisfactionCache(Context), AccessCheckingSFINAE(false),
|
|
|
|
InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
|
|
|
|
ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
|
|
|
|
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
|
2017-04-18 22:33:39 +08:00
|
|
|
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
|
|
|
|
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
|
2014-05-26 14:22:03 +08:00
|
|
|
TUScope = nullptr;
|
2019-06-15 16:32:56 +08:00
|
|
|
isConstantEvaluatedOverride = false;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-06-29 00:20:02 +08:00
|
|
|
LoadedExternalKnownNamespaces = false;
|
2012-03-07 04:05:56 +08:00
|
|
|
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
|
2014-05-26 14:22:03 +08:00
|
|
|
NSNumberLiteralMethods[I] = nullptr;
|
2012-03-07 04:05:56 +08:00
|
|
|
|
2018-10-31 04:31:30 +08:00
|
|
|
if (getLangOpts().ObjC)
|
2012-03-07 04:05:56 +08:00
|
|
|
NSAPIObj.reset(new NSAPI(Context));
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2008-07-01 18:37:29 +08:00
|
|
|
FieldCollector.reset(new CXXFieldCollector());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
// Tell diagnostics how to render things from the AST library.
|
2015-11-16 01:27:57 +08:00
|
|
|
Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);
|
2009-11-26 08:44:06 +08:00
|
|
|
|
2017-04-02 05:30:49 +08:00
|
|
|
ExprEvalContexts.emplace_back(
|
|
|
|
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
|
2018-07-13 02:45:41 +08:00
|
|
|
nullptr, ExpressionEvaluationContextRecord::EK_Other);
|
2010-08-25 16:40:02 +08:00
|
|
|
|
Misc typos fixes in ./lib folder
Summary: Found via `codespell -q 3 -I ../clang-whitelist.txt -L uint,importd,crasher,gonna,cant,ue,ons,orign,ned`
Reviewers: teemperor
Reviewed By: teemperor
Subscribers: teemperor, jholewinski, jvesely, nhaehnle, whisperity, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D55475
llvm-svn: 348755
2018-12-10 20:37:46 +08:00
|
|
|
// Initialization of data sharing attributes stack for OpenMP
|
2013-09-07 02:03:48 +08:00
|
|
|
InitDataSharingAttributesStack();
|
2017-07-28 22:41:21 +08:00
|
|
|
|
|
|
|
std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
|
2019-08-15 07:04:18 +08:00
|
|
|
std::make_unique<sema::SemaPPCallbacks>();
|
2017-07-28 22:41:21 +08:00
|
|
|
SemaPPCallbackHandler = Callbacks.get();
|
|
|
|
PP.addPPCallbacks(std::move(Callbacks));
|
|
|
|
SemaPPCallbackHandler->set(*this);
|
2010-08-13 06:51:45 +08:00
|
|
|
}
|
|
|
|
|
Add a key method to Sema to optimize debug info size
It turns out that the debug info describing the Sema class is an
appreciable percentage of the total object file size of objects in Sema.
By adding a key function, clang is able to optimize the debug info size
by emitting a forward declaration in TUs that do not define the key
function.
On Windows, with clang-cl, these are the total sizes of object files in
Sema before and after this change, compiling with optimizations and
debug info:
before: 335,012 KB
after: 278,116 KB
delta: -56,896 KB
percent: -17.0%
The effect on link time was negligible, despite having ~56MB less input.
On Linux, with clang, these are the same sizes using DWARF -g and
optimizations:
before: 603,756 KB
after: 515,340 KB
delta: -88,416 KB
percent: -14.6%
I didn't use type units, DWARF-5, fission, or any other special flags.
Reviewed By: thakis
Differential Revision: https://reviews.llvm.org/D70340
2019-11-16 03:22:02 +08:00
|
|
|
// Anchor Sema's type info to this TU.
|
|
|
|
void Sema::anchor() {}
|
|
|
|
|
2013-12-18 23:29:05 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-08-13 06:51:45 +08:00
|
|
|
void Sema::Initialize() {
|
|
|
|
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
|
|
|
|
SC->InitializeSema(*this);
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2010-08-13 06:51:45 +08:00
|
|
|
// Tell the external Sema source about this Sema object.
|
|
|
|
if (ExternalSemaSource *ExternalSema
|
|
|
|
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
|
|
|
|
ExternalSema->InitializeSema(*this);
|
2011-08-12 13:46:01 +08:00
|
|
|
|
2014-09-06 04:24:27 +08:00
|
|
|
// This needs to happen after ExternalSemaSource::InitializeSema(this) or we
|
|
|
|
// will not be able to merge any duplicate __va_list_tag decls correctly.
|
|
|
|
VAListTagName = PP.getIdentifierInfo("__va_list_tag");
|
|
|
|
|
2015-07-22 10:08:40 +08:00
|
|
|
if (!TUScope)
|
|
|
|
return;
|
|
|
|
|
2011-08-12 14:49:56 +08:00
|
|
|
// Initialize predefined 128-bit integer types, if needed.
|
2020-12-05 06:54:12 +08:00
|
|
|
if (Context.getTargetInfo().hasInt128Type() ||
|
|
|
|
(Context.getAuxTargetInfo() &&
|
|
|
|
Context.getAuxTargetInfo()->hasInt128Type())) {
|
2011-08-12 14:49:56 +08:00
|
|
|
// If either of the 128-bit integer types are unavailable to name lookup,
|
|
|
|
// define them now.
|
|
|
|
DeclarationName Int128 = &Context.Idents.get("__int128_t");
|
Make the loading of information attached to an IdentifierInfo from an
AST file more lazy, so that we don't eagerly load that information for
all known identifiers each time a new AST file is loaded. The eager
reloading made some sense in the context of precompiled headers, since
very few identifiers were defined before PCH load time. With modules,
however, a huge amount of code can get parsed before we see an
@import, so laziness becomes important here.
The approach taken to make this information lazy is fairly simple:
when we load a new AST file, we mark all of the existing identifiers
as being out-of-date. Whenever we want to access information that may
come from an AST (e.g., whether the identifier has a macro definition,
or what top-level declarations have that name), we check the
out-of-date bit and, if it's set, ask the AST reader to update the
IdentifierInfo from the AST files. The update is a merge, and we now
take care to merge declarations before/after imports with declarations
from multiple imports.
The results of this optimization are fairly dramatic. On a small
application that brings in 14 non-trivial modules, this takes modules
from being > 3x slower than a "perfect" PCH file down to 30% slower
for a full rebuild. A partial rebuild (where the PCH file or modules
can be re-used) is down to 7% slower. Making the PCH file just a
little imperfect (e.g., adding two smallish modules used by a bunch of
.m files that aren't in the PCH file) tips the scales in favor of the
modules approach, with 24% faster partial rebuilds.
This is just a first step; the lazy scheme could possibly be improved
by adding versioning, so we don't search into modules we already
searched. Moreover, we'll need similar lazy schemes for all of the
other lookup data structures, such as DeclContexts.
llvm-svn: 143100
2011-10-27 17:33:13 +08:00
|
|
|
if (IdResolver.begin(Int128) == IdResolver.end())
|
2011-08-12 14:49:56 +08:00
|
|
|
PushOnScopeChains(Context.getInt128Decl(), TUScope);
|
|
|
|
|
|
|
|
DeclarationName UInt128 = &Context.Idents.get("__uint128_t");
|
Make the loading of information attached to an IdentifierInfo from an
AST file more lazy, so that we don't eagerly load that information for
all known identifiers each time a new AST file is loaded. The eager
reloading made some sense in the context of precompiled headers, since
very few identifiers were defined before PCH load time. With modules,
however, a huge amount of code can get parsed before we see an
@import, so laziness becomes important here.
The approach taken to make this information lazy is fairly simple:
when we load a new AST file, we mark all of the existing identifiers
as being out-of-date. Whenever we want to access information that may
come from an AST (e.g., whether the identifier has a macro definition,
or what top-level declarations have that name), we check the
out-of-date bit and, if it's set, ask the AST reader to update the
IdentifierInfo from the AST files. The update is a merge, and we now
take care to merge declarations before/after imports with declarations
from multiple imports.
The results of this optimization are fairly dramatic. On a small
application that brings in 14 non-trivial modules, this takes modules
from being > 3x slower than a "perfect" PCH file down to 30% slower
for a full rebuild. A partial rebuild (where the PCH file or modules
can be re-used) is down to 7% slower. Making the PCH file just a
little imperfect (e.g., adding two smallish modules used by a bunch of
.m files that aren't in the PCH file) tips the scales in favor of the
modules approach, with 24% faster partial rebuilds.
This is just a first step; the lazy scheme could possibly be improved
by adding versioning, so we don't search into modules we already
searched. Moreover, we'll need similar lazy schemes for all of the
other lookup data structures, such as DeclContexts.
llvm-svn: 143100
2011-10-27 17:33:13 +08:00
|
|
|
if (IdResolver.begin(UInt128) == IdResolver.end())
|
2011-08-12 14:49:56 +08:00
|
|
|
PushOnScopeChains(Context.getUInt128Decl(), TUScope);
|
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-08-12 14:49:56 +08:00
|
|
|
|
2011-08-12 13:46:01 +08:00
|
|
|
// Initialize predefined Objective-C types:
|
2018-10-31 04:31:30 +08:00
|
|
|
if (getLangOpts().ObjC) {
|
2011-08-12 14:17:30 +08:00
|
|
|
// If 'SEL' does not yet refer to any declarations, make it refer to the
|
|
|
|
// predefined 'SEL'.
|
|
|
|
DeclarationName SEL = &Context.Idents.get("SEL");
|
Make the loading of information attached to an IdentifierInfo from an
AST file more lazy, so that we don't eagerly load that information for
all known identifiers each time a new AST file is loaded. The eager
reloading made some sense in the context of precompiled headers, since
very few identifiers were defined before PCH load time. With modules,
however, a huge amount of code can get parsed before we see an
@import, so laziness becomes important here.
The approach taken to make this information lazy is fairly simple:
when we load a new AST file, we mark all of the existing identifiers
as being out-of-date. Whenever we want to access information that may
come from an AST (e.g., whether the identifier has a macro definition,
or what top-level declarations have that name), we check the
out-of-date bit and, if it's set, ask the AST reader to update the
IdentifierInfo from the AST files. The update is a merge, and we now
take care to merge declarations before/after imports with declarations
from multiple imports.
The results of this optimization are fairly dramatic. On a small
application that brings in 14 non-trivial modules, this takes modules
from being > 3x slower than a "perfect" PCH file down to 30% slower
for a full rebuild. A partial rebuild (where the PCH file or modules
can be re-used) is down to 7% slower. Making the PCH file just a
little imperfect (e.g., adding two smallish modules used by a bunch of
.m files that aren't in the PCH file) tips the scales in favor of the
modules approach, with 24% faster partial rebuilds.
This is just a first step; the lazy scheme could possibly be improved
by adding versioning, so we don't search into modules we already
searched. Moreover, we'll need similar lazy schemes for all of the
other lookup data structures, such as DeclContexts.
llvm-svn: 143100
2011-10-27 17:33:13 +08:00
|
|
|
if (IdResolver.begin(SEL) == IdResolver.end())
|
2011-08-12 14:17:30 +08:00
|
|
|
PushOnScopeChains(Context.getObjCSelDecl(), TUScope);
|
|
|
|
|
2011-08-12 13:46:01 +08:00
|
|
|
// If 'id' does not yet refer to any declarations, make it refer to the
|
|
|
|
// predefined 'id'.
|
|
|
|
DeclarationName Id = &Context.Idents.get("id");
|
Make the loading of information attached to an IdentifierInfo from an
AST file more lazy, so that we don't eagerly load that information for
all known identifiers each time a new AST file is loaded. The eager
reloading made some sense in the context of precompiled headers, since
very few identifiers were defined before PCH load time. With modules,
however, a huge amount of code can get parsed before we see an
@import, so laziness becomes important here.
The approach taken to make this information lazy is fairly simple:
when we load a new AST file, we mark all of the existing identifiers
as being out-of-date. Whenever we want to access information that may
come from an AST (e.g., whether the identifier has a macro definition,
or what top-level declarations have that name), we check the
out-of-date bit and, if it's set, ask the AST reader to update the
IdentifierInfo from the AST files. The update is a merge, and we now
take care to merge declarations before/after imports with declarations
from multiple imports.
The results of this optimization are fairly dramatic. On a small
application that brings in 14 non-trivial modules, this takes modules
from being > 3x slower than a "perfect" PCH file down to 30% slower
for a full rebuild. A partial rebuild (where the PCH file or modules
can be re-used) is down to 7% slower. Making the PCH file just a
little imperfect (e.g., adding two smallish modules used by a bunch of
.m files that aren't in the PCH file) tips the scales in favor of the
modules approach, with 24% faster partial rebuilds.
This is just a first step; the lazy scheme could possibly be improved
by adding versioning, so we don't search into modules we already
searched. Moreover, we'll need similar lazy schemes for all of the
other lookup data structures, such as DeclContexts.
llvm-svn: 143100
2011-10-27 17:33:13 +08:00
|
|
|
if (IdResolver.begin(Id) == IdResolver.end())
|
2011-08-12 13:46:01 +08:00
|
|
|
PushOnScopeChains(Context.getObjCIdDecl(), TUScope);
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-08-12 13:59:41 +08:00
|
|
|
// Create the built-in typedef for 'Class'.
|
|
|
|
DeclarationName Class = &Context.Idents.get("Class");
|
Make the loading of information attached to an IdentifierInfo from an
AST file more lazy, so that we don't eagerly load that information for
all known identifiers each time a new AST file is loaded. The eager
reloading made some sense in the context of precompiled headers, since
very few identifiers were defined before PCH load time. With modules,
however, a huge amount of code can get parsed before we see an
@import, so laziness becomes important here.
The approach taken to make this information lazy is fairly simple:
when we load a new AST file, we mark all of the existing identifiers
as being out-of-date. Whenever we want to access information that may
come from an AST (e.g., whether the identifier has a macro definition,
or what top-level declarations have that name), we check the
out-of-date bit and, if it's set, ask the AST reader to update the
IdentifierInfo from the AST files. The update is a merge, and we now
take care to merge declarations before/after imports with declarations
from multiple imports.
The results of this optimization are fairly dramatic. On a small
application that brings in 14 non-trivial modules, this takes modules
from being > 3x slower than a "perfect" PCH file down to 30% slower
for a full rebuild. A partial rebuild (where the PCH file or modules
can be re-used) is down to 7% slower. Making the PCH file just a
little imperfect (e.g., adding two smallish modules used by a bunch of
.m files that aren't in the PCH file) tips the scales in favor of the
modules approach, with 24% faster partial rebuilds.
This is just a first step; the lazy scheme could possibly be improved
by adding versioning, so we don't search into modules we already
searched. Moreover, we'll need similar lazy schemes for all of the
other lookup data structures, such as DeclContexts.
llvm-svn: 143100
2011-10-27 17:33:13 +08:00
|
|
|
if (IdResolver.begin(Class) == IdResolver.end())
|
2011-08-12 13:59:41 +08:00
|
|
|
PushOnScopeChains(Context.getObjCClassDecl(), TUScope);
|
2012-01-18 02:09:05 +08:00
|
|
|
|
|
|
|
// Create the built-in forward declaratino for 'Protocol'.
|
|
|
|
DeclarationName Protocol = &Context.Idents.get("Protocol");
|
|
|
|
if (IdResolver.begin(Protocol) == IdResolver.end())
|
|
|
|
PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
|
2011-08-12 13:46:01 +08:00
|
|
|
}
|
2012-06-16 11:34:49 +08:00
|
|
|
|
2016-02-04 08:55:24 +08:00
|
|
|
// Create the internal type for the *StringMakeConstantString builtins.
|
|
|
|
DeclarationName ConstantString = &Context.Idents.get("__NSConstantString");
|
|
|
|
if (IdResolver.begin(ConstantString) == IdResolver.end())
|
|
|
|
PushOnScopeChains(Context.getCFConstantStringDecl(), TUScope);
|
|
|
|
|
2014-01-04 23:25:02 +08:00
|
|
|
// Initialize Microsoft "predefined C++ types".
|
2015-11-16 01:27:57 +08:00
|
|
|
if (getLangOpts().MSVCCompat) {
|
|
|
|
if (getLangOpts().CPlusPlus &&
|
2015-02-18 10:28:13 +08:00
|
|
|
IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
|
2014-01-04 23:25:02 +08:00
|
|
|
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
|
|
|
|
TUScope);
|
2014-01-14 14:19:35 +08:00
|
|
|
|
|
|
|
addImplicitTypedef("size_t", Context.getSizeType());
|
2014-01-04 23:25:02 +08:00
|
|
|
}
|
|
|
|
|
2016-12-18 13:18:55 +08:00
|
|
|
// Initialize predefined OpenCL types and supported extensions and (optional)
|
|
|
|
// core features.
|
2015-11-16 01:27:57 +08:00
|
|
|
if (getLangOpts().OpenCL) {
|
2019-02-08 01:32:37 +08:00
|
|
|
getOpenCLOptions().addSupport(
|
2021-01-26 00:23:58 +08:00
|
|
|
Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
|
2013-12-18 23:29:05 +08:00
|
|
|
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
|
|
|
|
addImplicitTypedef("event_t", Context.OCLEventTy);
|
2019-02-08 01:32:37 +08:00
|
|
|
if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) {
|
2015-09-15 19:18:52 +08:00
|
|
|
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
|
|
|
|
addImplicitTypedef("queue_t", Context.OCLQueueTy);
|
|
|
|
addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
|
2015-03-18 20:55:29 +08:00
|
|
|
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
|
|
|
|
addImplicitTypedef("atomic_uint",
|
|
|
|
Context.getAtomicType(Context.UnsignedIntTy));
|
|
|
|
addImplicitTypedef("atomic_float",
|
|
|
|
Context.getAtomicType(Context.FloatTy));
|
|
|
|
// OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
|
|
|
|
// 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
|
|
|
|
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
|
2016-12-18 13:18:55 +08:00
|
|
|
auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
|
|
|
|
addImplicitTypedef("atomic_size_t", AtomicSizeT);
|
|
|
|
|
|
|
|
// OpenCL v2.0 s6.13.11.6:
|
|
|
|
// - The atomic_long and atomic_ulong types are supported if the
|
|
|
|
// cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
|
|
|
|
// extensions are supported.
|
|
|
|
// - The atomic_double type is only supported if double precision
|
|
|
|
// is supported and the cl_khr_int64_base_atomics and
|
|
|
|
// cl_khr_int64_extended_atomics extensions are supported.
|
|
|
|
// - If the device address space is 64-bits, the data types
|
|
|
|
// atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
|
|
|
|
// atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
|
|
|
|
// cl_khr_int64_extended_atomics extensions are supported.
|
|
|
|
std::vector<QualType> Atomic64BitTypes;
|
2021-03-05 21:23:49 +08:00
|
|
|
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);
|
|
|
|
setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
|
|
|
|
Atomic64BitTypes.push_back(AtomicDoubleT);
|
|
|
|
}
|
|
|
|
auto AtomicLongT = Context.getAtomicType(Context.LongTy);
|
|
|
|
auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
|
|
|
|
auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
|
|
|
|
auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
|
|
|
|
auto AtomicPtrDiffT =
|
|
|
|
Context.getAtomicType(Context.getPointerDiffType());
|
|
|
|
|
|
|
|
addImplicitTypedef("atomic_long", AtomicLongT);
|
|
|
|
addImplicitTypedef("atomic_ulong", AtomicULongT);
|
|
|
|
addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
|
|
|
|
addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
|
|
|
|
addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
|
|
|
|
|
|
|
|
Atomic64BitTypes.push_back(AtomicLongT);
|
|
|
|
Atomic64BitTypes.push_back(AtomicULongT);
|
|
|
|
if (Context.getTypeSize(AtomicSizeT) == 64) {
|
|
|
|
Atomic64BitTypes.push_back(AtomicSizeT);
|
|
|
|
Atomic64BitTypes.push_back(AtomicIntPtrT);
|
|
|
|
Atomic64BitTypes.push_back(AtomicUIntPtrT);
|
|
|
|
Atomic64BitTypes.push_back(AtomicPtrDiffT);
|
|
|
|
}
|
2016-12-18 13:18:55 +08:00
|
|
|
}
|
2021-03-05 21:23:49 +08:00
|
|
|
|
2016-12-18 13:18:55 +08:00
|
|
|
for (auto &I : Atomic64BitTypes)
|
|
|
|
setOpenCLExtensionForType(I,
|
|
|
|
"cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
|
2015-03-18 20:55:29 +08:00
|
|
|
}
|
2016-12-18 13:18:55 +08:00
|
|
|
|
|
|
|
|
2021-03-05 21:23:49 +08:00
|
|
|
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
|
|
|
|
if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \
|
|
|
|
addImplicitTypedef(#ExtType, Context.Id##Ty); \
|
|
|
|
setOpenCLExtensionForType(Context.Id##Ty, #Ext); \
|
|
|
|
}
|
2018-11-08 19:25:41 +08:00
|
|
|
#include "clang/Basic/OpenCLExtensionTypes.def"
|
2019-08-09 16:52:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Context.getTargetInfo().hasAArch64SVETypes()) {
|
|
|
|
#define SVE_TYPE(Name, Id, SingletonId) \
|
|
|
|
addImplicitTypedef(Name, Context.SingletonId);
|
|
|
|
#include "clang/Basic/AArch64SVEACLETypes.def"
|
|
|
|
}
|
2013-12-18 23:29:05 +08:00
|
|
|
|
2020-10-29 02:14:48 +08:00
|
|
|
if (Context.getTargetInfo().getTriple().isPPC64() &&
|
2020-12-16 05:08:09 +08:00
|
|
|
Context.getTargetInfo().hasFeature("paired-vector-memops")) {
|
|
|
|
if (Context.getTargetInfo().hasFeature("mma")) {
|
|
|
|
#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) \
|
2020-10-29 02:14:48 +08:00
|
|
|
addImplicitTypedef(#Name, Context.Id##Ty);
|
|
|
|
#include "clang/Basic/PPCTypes.def"
|
|
|
|
}
|
|
|
|
|
2021-02-04 12:57:36 +08:00
|
|
|
if (Context.getTargetInfo().hasRISCVVTypes()) {
|
|
|
|
#define RVV_TYPE(Name, Id, SingletonId) \
|
|
|
|
addImplicitTypedef(Name, Context.SingletonId);
|
|
|
|
#include "clang/Basic/RISCVVTypes.def"
|
|
|
|
}
|
|
|
|
|
2015-11-16 01:27:57 +08:00
|
|
|
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
|
2015-09-18 04:55:33 +08:00
|
|
|
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
|
|
|
|
if (IdResolver.begin(MSVaList) == IdResolver.end())
|
|
|
|
PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
|
|
|
|
}
|
|
|
|
|
2012-06-16 11:34:49 +08:00
|
|
|
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
|
|
|
|
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
|
|
|
|
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
|
2007-02-28 09:22:02 +08:00
|
|
|
}
|
2006-11-10 14:20:45 +08:00
|
|
|
|
2010-01-10 20:58:08 +08:00
|
|
|
Sema::~Sema() {
|
2020-12-11 08:49:27 +08:00
|
|
|
assert(InstantiatingSpecializations.empty() &&
|
|
|
|
"failed to clean up an InstantiatingTemplate?");
|
|
|
|
|
2010-08-05 14:57:20 +08:00
|
|
|
if (VisContext) FreeVisContext();
|
2018-03-13 05:43:02 +08:00
|
|
|
|
2010-08-25 16:40:02 +08:00
|
|
|
// Kill all the active scopes.
|
2018-03-13 05:43:02 +08:00
|
|
|
for (sema::FunctionScopeInfo *FSI : FunctionScopes)
|
2019-05-31 08:45:09 +08:00
|
|
|
delete FSI;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2010-08-13 06:51:45 +08:00
|
|
|
// Tell the SemaConsumer to forget about us; we're going out of scope.
|
|
|
|
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
|
|
|
|
SC->ForgetSema();
|
|
|
|
|
|
|
|
// Detach from the external Sema source.
|
|
|
|
if (ExternalSemaSource *ExternalSema
|
2010-08-13 11:15:25 +08:00
|
|
|
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
|
2010-08-13 06:51:45 +08:00
|
|
|
ExternalSema->ForgetSema();
|
2012-10-19 03:05:02 +08:00
|
|
|
|
|
|
|
// If Sema's ExternalSource is the multiplexer - we own it.
|
|
|
|
if (isMultiplexExternalSource)
|
|
|
|
delete ExternalSource;
|
2013-09-07 02:03:48 +08:00
|
|
|
|
2020-01-22 08:50:12 +08:00
|
|
|
// Delete cached satisfactions.
|
|
|
|
std::vector<ConstraintSatisfaction *> Satisfactions;
|
|
|
|
Satisfactions.reserve(Satisfactions.size());
|
|
|
|
for (auto &Node : SatisfactionCache)
|
|
|
|
Satisfactions.push_back(&Node);
|
|
|
|
for (auto *Node : Satisfactions)
|
|
|
|
delete Node;
|
|
|
|
|
2015-02-04 06:11:04 +08:00
|
|
|
threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);
|
|
|
|
|
2013-09-07 02:03:48 +08:00
|
|
|
// Destroys data sharing attributes stack for OpenMP
|
|
|
|
DestroyDataSharingAttributesStack();
|
2014-11-22 02:48:06 +08:00
|
|
|
|
2017-07-28 22:41:21 +08:00
|
|
|
// Detach from the PP callback handler which outlives Sema since it's owned
|
|
|
|
// by the preprocessor.
|
|
|
|
SemaPPCallbackHandler->reset();
|
2010-01-10 20:58:08 +08:00
|
|
|
}
|
|
|
|
|
Improve behavior in the case of stack exhaustion.
Summary:
Clang performs various recursive operations (such as template instantiation),
and may use non-trivial amounts of stack space in each recursive step (for
instance, due to recursive AST walks). While we try to keep the stack space
used by such steps to a minimum and we have explicit limits on the number of
such steps we perform, it's impractical to guarantee that we won't blow out the
stack on deeply recursive template instantiations on complex ASTs, even with
only a moderately high instantiation depth limit.
The user experience in these cases is generally terrible: we crash with
no hint of what went wrong. Under this patch, we attempt to do better:
* Detect when the stack is nearly exhausted, and produce a warning with a
nice template instantiation backtrace, telling the user that we might
run slowly or crash.
* For cases where we're forced to trigger recursive template
instantiation in arbitrarily-deeply-nested contexts, check whether
we're nearly out of stack space and allocate a new stack (by spawning
a new thread) after producing the warning.
Reviewers: rnk, aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66361
llvm-svn: 369940
2019-08-27 02:18:07 +08:00
|
|
|
void Sema::warnStackExhausted(SourceLocation Loc) {
|
|
|
|
// Only warn about this once.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
/// makeUnavailableInSystemHeader - There is an error in the current
|
|
|
|
/// context. If we're still in a system header, and we can plausibly
|
|
|
|
/// make the relevant declaration unavailable instead of erroring, do
|
|
|
|
/// so and return true.
|
|
|
|
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
|
2015-10-28 13:03:19 +08:00
|
|
|
UnavailableAttr::ImplicitReason reason) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// If we're not in a function, it's an error.
|
|
|
|
FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
|
|
|
|
if (!fn) return false;
|
|
|
|
|
|
|
|
// If we're in template instantiation, it's an error.
|
2017-02-21 09:17:38 +08:00
|
|
|
if (inTemplateInstantiation())
|
2011-06-16 07:02:42 +08:00
|
|
|
return false;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// If that function's not in a system header, it's an error.
|
|
|
|
if (!Context.getSourceManager().isInSystemHeader(loc))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If the function is already unavailable, it's not an error.
|
|
|
|
if (fn->hasAttr<UnavailableAttr>()) return true;
|
|
|
|
|
2015-10-28 13:03:19 +08:00
|
|
|
fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc));
|
2011-06-16 07:02:42 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-04-25 00:28:06 +08:00
|
|
|
ASTMutationListener *Sema::getASTMutationListener() const {
|
|
|
|
return getASTConsumer().GetASTMutationListener();
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
///Registers an external source. If an external source already exists,
|
2012-10-19 03:05:02 +08:00
|
|
|
/// creates a multiplex external source and appends to it.
|
|
|
|
///
|
|
|
|
///\param[in] E - A non-null external sema source.
|
|
|
|
///
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Print out statistics about the semantic analysis.
|
2011-07-07 00:21:37 +08:00
|
|
|
void Sema::PrintStats() const {
|
|
|
|
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
|
|
|
|
llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
|
|
|
|
|
|
|
|
BumpAlloc.PrintStats();
|
|
|
|
AnalysisWarnings.PrintStats();
|
|
|
|
}
|
|
|
|
|
2015-12-15 06:00:49 +08:00
|
|
|
void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
|
|
|
|
QualType SrcType,
|
|
|
|
SourceLocation Loc) {
|
|
|
|
Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
|
2020-12-07 22:14:25 +08:00
|
|
|
if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
|
|
|
|
*ExprNullability != NullabilityKind::NullableResult))
|
2015-12-15 06:00:49 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
|
|
|
|
if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType;
|
|
|
|
}
|
|
|
|
|
2017-05-06 00:11:08 +08:00
|
|
|
void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
|
[Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.
Summary:
The warning was initially introduced in D32914 by @thakis,
and the concerns were raised there, and later in rL302247
and PR33771.
I do believe that it makes sense to relax the diagnostic
e.g. in this case, when the expression originates from the
system header, which can not be modified. This prevents
adoption for the diagnostic for codebases which use pthreads
(`PTHREAD_MUTEX_INITIALIZER`), gtest, etc.
As @malcolm.parsons suggests, it *may* make sense to also
not warn for the template types, but it is not obvious to
me how to do that in here.
Though, it still makes sense to complain about `NULL` macro.
While there, add more tests.
Reviewers: dblaikie, thakis, rsmith, rjmccall, aaron.ballman
Reviewed By: thakis
Subscribers: Rakete1111, hans, cfe-commits, thakis, malcolm.parsons
Tags: #clang
Differential Revision: https://reviews.llvm.org/D38954
llvm-svn: 316662
2017-10-26 21:18:14 +08:00
|
|
|
if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
|
2018-08-10 05:08:08 +08:00
|
|
|
E->getBeginLoc()))
|
[Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.
Summary:
The warning was initially introduced in D32914 by @thakis,
and the concerns were raised there, and later in rL302247
and PR33771.
I do believe that it makes sense to relax the diagnostic
e.g. in this case, when the expression originates from the
system header, which can not be modified. This prevents
adoption for the diagnostic for codebases which use pthreads
(`PTHREAD_MUTEX_INITIALIZER`), gtest, etc.
As @malcolm.parsons suggests, it *may* make sense to also
not warn for the template types, but it is not obvious to
me how to do that in here.
Though, it still makes sense to complain about `NULL` macro.
While there, add more tests.
Reviewers: dblaikie, thakis, rsmith, rjmccall, aaron.ballman
Reviewed By: thakis
Subscribers: Rakete1111, hans, cfe-commits, thakis, malcolm.parsons
Tags: #clang
Differential Revision: https://reviews.llvm.org/D38954
llvm-svn: 316662
2017-10-26 21:18:14 +08:00
|
|
|
return;
|
|
|
|
// nullptr only exists from C++11 on, so don't warn on its absence earlier.
|
|
|
|
if (!getLangOpts().CPlusPlus11)
|
|
|
|
return;
|
|
|
|
|
2017-05-06 00:11:08 +08:00
|
|
|
if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
|
|
|
|
return;
|
2017-10-26 04:23:13 +08:00
|
|
|
if (E->IgnoreParenImpCasts()->getType()->isNullPtrType())
|
2017-05-06 00:11:08 +08:00
|
|
|
return;
|
[Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.
Summary:
The warning was initially introduced in D32914 by @thakis,
and the concerns were raised there, and later in rL302247
and PR33771.
I do believe that it makes sense to relax the diagnostic
e.g. in this case, when the expression originates from the
system header, which can not be modified. This prevents
adoption for the diagnostic for codebases which use pthreads
(`PTHREAD_MUTEX_INITIALIZER`), gtest, etc.
As @malcolm.parsons suggests, it *may* make sense to also
not warn for the template types, but it is not obvious to
me how to do that in here.
Though, it still makes sense to complain about `NULL` macro.
While there, add more tests.
Reviewers: dblaikie, thakis, rsmith, rjmccall, aaron.ballman
Reviewed By: thakis
Subscribers: Rakete1111, hans, cfe-commits, thakis, malcolm.parsons
Tags: #clang
Differential Revision: https://reviews.llvm.org/D38954
llvm-svn: 316662
2017-10-26 21:18:14 +08:00
|
|
|
|
2021-02-04 06:57:19 +08:00
|
|
|
// Don't diagnose the conversion from a 0 literal to a null pointer argument
|
|
|
|
// in a synthesized call to operator<=>.
|
|
|
|
if (!CodeSynthesisContexts.empty() &&
|
|
|
|
CodeSynthesisContexts.back().Kind ==
|
|
|
|
CodeSynthesisContext::RewritingOperatorAsSpaceship)
|
|
|
|
return;
|
|
|
|
|
[Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.
Summary:
The warning was initially introduced in D32914 by @thakis,
and the concerns were raised there, and later in rL302247
and PR33771.
I do believe that it makes sense to relax the diagnostic
e.g. in this case, when the expression originates from the
system header, which can not be modified. This prevents
adoption for the diagnostic for codebases which use pthreads
(`PTHREAD_MUTEX_INITIALIZER`), gtest, etc.
As @malcolm.parsons suggests, it *may* make sense to also
not warn for the template types, but it is not obvious to
me how to do that in here.
Though, it still makes sense to complain about `NULL` macro.
While there, add more tests.
Reviewers: dblaikie, thakis, rsmith, rjmccall, aaron.ballman
Reviewed By: thakis
Subscribers: Rakete1111, hans, cfe-commits, thakis, malcolm.parsons
Tags: #clang
Differential Revision: https://reviews.llvm.org/D38954
llvm-svn: 316662
2017-10-26 21:18:14 +08:00
|
|
|
// If it is a macro from system header, and if the macro name is not "NULL",
|
|
|
|
// do not warn.
|
2018-08-10 05:08:08 +08:00
|
|
|
SourceLocation MaybeMacroLoc = E->getBeginLoc();
|
[Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.
Summary:
The warning was initially introduced in D32914 by @thakis,
and the concerns were raised there, and later in rL302247
and PR33771.
I do believe that it makes sense to relax the diagnostic
e.g. in this case, when the expression originates from the
system header, which can not be modified. This prevents
adoption for the diagnostic for codebases which use pthreads
(`PTHREAD_MUTEX_INITIALIZER`), gtest, etc.
As @malcolm.parsons suggests, it *may* make sense to also
not warn for the template types, but it is not obvious to
me how to do that in here.
Though, it still makes sense to complain about `NULL` macro.
While there, add more tests.
Reviewers: dblaikie, thakis, rsmith, rjmccall, aaron.ballman
Reviewed By: thakis
Subscribers: Rakete1111, hans, cfe-commits, thakis, malcolm.parsons
Tags: #clang
Differential Revision: https://reviews.llvm.org/D38954
llvm-svn: 316662
2017-10-26 21:18:14 +08:00
|
|
|
if (Diags.getSuppressSystemWarnings() &&
|
|
|
|
SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
|
|
|
|
!findMacroSpelling(MaybeMacroLoc, "NULL"))
|
2017-05-06 00:11:08 +08:00
|
|
|
return;
|
|
|
|
|
2018-08-10 05:08:08 +08:00
|
|
|
Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant)
|
2017-05-06 00:11:08 +08:00
|
|
|
<< FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
|
|
|
|
}
|
|
|
|
|
2011-11-30 06:48:16 +08:00
|
|
|
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
|
|
|
/// If there is already an implicit cast, merge into the existing one.
|
|
|
|
/// The result is of the given category.
|
|
|
|
ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
|
|
|
|
CastKind Kind, ExprValueKind VK,
|
|
|
|
const CXXCastPath *BasePath,
|
|
|
|
CheckedConversionKind CCK) {
|
2011-10-28 11:31:48 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
if (VK == VK_RValue && !E->isRValue()) {
|
|
|
|
switch (Kind) {
|
|
|
|
default:
|
2020-07-22 16:03:51 +08:00
|
|
|
llvm_unreachable(("can't implicitly cast lvalue to rvalue with this cast "
|
|
|
|
"kind: " +
|
|
|
|
std::string(CastExpr::getCastKindName(Kind)))
|
|
|
|
.c_str());
|
2019-06-21 03:49:13 +08:00
|
|
|
case CK_Dependent:
|
2011-10-28 11:31:48 +08:00
|
|
|
case CK_LValueToRValue:
|
|
|
|
case CK_ArrayToPointerDecay:
|
|
|
|
case CK_FunctionToPointerDecay:
|
|
|
|
case CK_ToVoid:
|
2018-07-19 02:01:41 +08:00
|
|
|
case CK_NonAtomicToAtomic:
|
2011-10-28 11:31:48 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-06-21 03:49:13 +08:00
|
|
|
assert((VK == VK_RValue || Kind == CK_Dependent || !E->isRValue()) &&
|
|
|
|
"can't cast rvalue to lvalue");
|
2011-10-28 11:31:48 +08:00
|
|
|
#endif
|
|
|
|
|
2018-08-10 05:08:08 +08:00
|
|
|
diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
|
2017-05-06 00:11:08 +08:00
|
|
|
diagnoseZeroToNullptrConversion(Kind, E);
|
2015-06-20 02:13:19 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType ExprTy = Context.getCanonicalType(E->getType());
|
2008-09-04 16:38:01 +08:00
|
|
|
QualType TypeTy = Context.getCanonicalType(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-04 16:38:01 +08:00
|
|
|
if (ExprTy == TypeTy)
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2016-12-05 15:49:14 +08:00
|
|
|
// C++1z [conv.array]: The temporary materialization conversion is applied.
|
|
|
|
// We also use this to fuel C++ DR1213, which applies to C++11 onwards.
|
|
|
|
if (Kind == CK_ArrayToPointerDecay && getLangOpts().CPlusPlus &&
|
|
|
|
E->getValueKind() == VK_RValue) {
|
|
|
|
// The temporary is an lvalue in C++98 and an xvalue otherwise.
|
|
|
|
ExprResult Materialized = CreateMaterializeTemporaryExpr(
|
|
|
|
E->getType(), E, !getLangOpts().CPlusPlus11);
|
|
|
|
if (Materialized.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
E = Materialized.get();
|
|
|
|
}
|
|
|
|
|
2011-11-30 06:48:16 +08:00
|
|
|
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
|
|
|
|
ImpCast->setType(Ty);
|
|
|
|
ImpCast->setValueKind(VK);
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2011-11-30 06:48:16 +08:00
|
|
|
}
|
2009-09-15 13:28:24 +08:00
|
|
|
}
|
|
|
|
|
2020-09-12 22:54:14 +08:00
|
|
|
return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK,
|
|
|
|
CurFPFeatureOverrides());
|
2010-07-20 12:20:21 +08:00
|
|
|
}
|
|
|
|
|
2011-04-07 17:26:19 +08:00
|
|
|
/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
|
|
|
|
/// to the conversion from scalar type ScalarTy to the Boolean type.
|
|
|
|
CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
|
|
|
|
switch (ScalarTy->getScalarTypeKind()) {
|
|
|
|
case Type::STK_Bool: return CK_NoOp;
|
2011-09-09 13:25:32 +08:00
|
|
|
case Type::STK_CPointer: return CK_PointerToBoolean;
|
|
|
|
case Type::STK_BlockPointer: return CK_PointerToBoolean;
|
|
|
|
case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean;
|
2011-04-07 17:26:19 +08:00
|
|
|
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;
|
2018-10-24 01:55:35 +08:00
|
|
|
case Type::STK_FixedPoint: return CK_FixedPointToBoolean;
|
2011-04-07 17:26:19 +08:00
|
|
|
}
|
2017-12-09 07:29:59 +08:00
|
|
|
llvm_unreachable("unknown scalar type kind");
|
2011-04-07 17:26:19 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Used to prune the decls of Sema's UnusedFileScopedDecls vector.
|
2010-08-15 09:15:20 +08:00
|
|
|
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
|
2013-01-09 03:43:34 +08:00
|
|
|
if (D->getMostRecentDecl()->isUsed())
|
2010-08-15 09:15:20 +08:00
|
|
|
return true;
|
|
|
|
|
2013-05-13 08:12:11 +08:00
|
|
|
if (D->isExternallyVisible())
|
2013-03-14 11:07:35 +08:00
|
|
|
return true;
|
|
|
|
|
2010-08-15 09:15:20 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2017-05-09 19:25:41 +08:00
|
|
|
// If this is a function template and none of its specializations is used,
|
|
|
|
// we should warn.
|
|
|
|
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate())
|
|
|
|
for (const auto *Spec : Template->specializations())
|
|
|
|
if (ShouldRemoveFromUnused(SemaRef, Spec))
|
|
|
|
return true;
|
|
|
|
|
2010-08-15 09:15:20 +08:00
|
|
|
// UnusedFileScopedDecls stores the first declaration.
|
|
|
|
// The declaration may have become definition so check again.
|
|
|
|
const FunctionDecl *DeclToCheck;
|
|
|
|
if (FD->hasBody(DeclToCheck))
|
|
|
|
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
|
|
|
|
|
|
|
|
// Later redecls may add new information resulting in not having to warn,
|
|
|
|
// so check again.
|
2012-01-15 00:38:05 +08:00
|
|
|
DeclToCheck = FD->getMostRecentDecl();
|
2010-08-15 09:15:20 +08:00
|
|
|
if (DeclToCheck != FD)
|
|
|
|
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
2013-09-11 05:10:25 +08:00
|
|
|
// If a variable usable in constant expressions is referenced,
|
|
|
|
// don't warn if it isn't used: if the value of a variable is required
|
|
|
|
// for the computation of a constant expression, it doesn't make sense to
|
|
|
|
// warn even if the variable isn't odr-used. (isReferenced doesn't
|
|
|
|
// precisely reflect that, but it's a decent approximation.)
|
|
|
|
if (VD->isReferenced() &&
|
2019-06-12 01:50:32 +08:00
|
|
|
VD->mightBeUsableInConstantExpressions(SemaRef->Context))
|
2013-09-11 05:10:25 +08:00
|
|
|
return true;
|
|
|
|
|
2017-05-09 19:25:41 +08:00
|
|
|
if (VarTemplateDecl *Template = VD->getDescribedVarTemplate())
|
|
|
|
// If this is a variable template and none of its specializations is used,
|
|
|
|
// we should warn.
|
|
|
|
for (const auto *Spec : Template->specializations())
|
|
|
|
if (ShouldRemoveFromUnused(SemaRef, Spec))
|
|
|
|
return true;
|
|
|
|
|
2010-08-15 09:15:20 +08:00
|
|
|
// UnusedFileScopedDecls stores the first declaration.
|
|
|
|
// The declaration may have become definition so check again.
|
2013-01-20 09:04:14 +08:00
|
|
|
const VarDecl *DeclToCheck = VD->getDefinition();
|
2010-08-15 09:15:20 +08:00
|
|
|
if (DeclToCheck)
|
|
|
|
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
|
|
|
|
|
|
|
|
// Later redecls may add new information resulting in not having to warn,
|
|
|
|
// so check again.
|
2012-01-15 00:38:05 +08:00
|
|
|
DeclToCheck = VD->getMostRecentDecl();
|
2010-08-15 09:15:20 +08:00
|
|
|
if (DeclToCheck != VD)
|
|
|
|
return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-20 15:22:00 +08:00
|
|
|
static bool isFunctionOrVarDeclExternC(NamedDecl *ND) {
|
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(ND))
|
|
|
|
return FD->isExternC();
|
|
|
|
return cast<VarDecl>(ND)->isExternC();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determine whether ND is an external-linkage function or variable whose
|
|
|
|
/// type has no linkage.
|
|
|
|
bool Sema::isExternalWithNoLinkageType(ValueDecl *VD) {
|
|
|
|
// Note: it's not quite enough to check whether VD has UniqueExternalLinkage,
|
|
|
|
// because we also want to catch the case where its type has VisibleNoLinkage,
|
|
|
|
// which does not affect the linkage of VD.
|
|
|
|
return getLangOpts().CPlusPlus && VD->hasExternalFormalLinkage() &&
|
|
|
|
!isExternalFormalLinkage(VD->getType()->getLinkage()) &&
|
|
|
|
!isFunctionOrVarDeclExternC(VD);
|
|
|
|
}
|
|
|
|
|
2016-06-25 08:15:56 +08:00
|
|
|
/// Obtains a sorted list of functions and variables that are undefined but
|
|
|
|
/// ODR-used.
|
2013-02-01 16:13:20 +08:00
|
|
|
void Sema::getUndefinedButUsed(
|
2013-01-31 11:23:57 +08:00
|
|
|
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
|
2016-03-26 05:49:43 +08:00
|
|
|
for (const auto &UndefinedUse : UndefinedButUsed) {
|
|
|
|
NamedDecl *ND = UndefinedUse.first;
|
2011-02-19 10:53:41 +08:00
|
|
|
|
|
|
|
// Ignore attributes that have become invalid.
|
2013-01-31 11:23:57 +08:00
|
|
|
if (ND->isInvalidDecl()) continue;
|
2011-02-19 10:53:41 +08:00
|
|
|
|
|
|
|
// __attribute__((weakref)) is basically a definition.
|
2013-01-31 11:23:57 +08:00
|
|
|
if (ND->hasAttr<WeakRefAttr>()) continue;
|
2011-02-19 10:53:41 +08:00
|
|
|
|
2017-08-04 03:24:27 +08:00
|
|
|
if (isa<CXXDeductionGuideDecl>(ND))
|
|
|
|
continue;
|
|
|
|
|
2017-09-20 15:22:00 +08:00
|
|
|
if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
|
|
|
|
// An exported function will always be emitted when defined, so even if
|
|
|
|
// the function is inline, it doesn't have to be emitted in this TU. An
|
|
|
|
// imported function implies that it has been exported somewhere else.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-01-31 11:23:57 +08:00
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
|
|
|
|
if (FD->isDefined())
|
2011-02-19 10:53:41 +08:00
|
|
|
continue;
|
2013-05-13 08:12:11 +08:00
|
|
|
if (FD->isExternallyVisible() &&
|
2017-09-20 15:22:00 +08:00
|
|
|
!isExternalWithNoLinkageType(FD) &&
|
2018-10-04 23:49:42 +08:00
|
|
|
!FD->getMostRecentDecl()->isInlined() &&
|
|
|
|
!FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
|
2013-02-01 16:13:20 +08:00
|
|
|
continue;
|
2018-06-21 05:12:20 +08:00
|
|
|
if (FD->getBuiltinID())
|
|
|
|
continue;
|
2011-02-19 10:53:41 +08:00
|
|
|
} else {
|
2016-06-25 08:15:56 +08:00
|
|
|
auto *VD = cast<VarDecl>(ND);
|
|
|
|
if (VD->hasDefinition() != VarDecl::DeclarationOnly)
|
2011-02-19 10:53:41 +08:00
|
|
|
continue;
|
2017-09-20 15:22:00 +08:00
|
|
|
if (VD->isExternallyVisible() &&
|
|
|
|
!isExternalWithNoLinkageType(VD) &&
|
2018-10-04 23:49:42 +08:00
|
|
|
!VD->getMostRecentDecl()->isInline() &&
|
|
|
|
!VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
|
2013-02-01 16:13:20 +08:00
|
|
|
continue;
|
2018-05-18 00:15:07 +08:00
|
|
|
|
|
|
|
// Skip VarDecls that lack formal definitions but which we know are in
|
|
|
|
// fact defined somewhere.
|
|
|
|
if (VD->isKnownToBeDefined())
|
|
|
|
continue;
|
2011-02-19 10:53:41 +08:00
|
|
|
}
|
|
|
|
|
2016-03-26 05:49:43 +08:00
|
|
|
Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
|
2013-01-31 11:23:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 16:13:20 +08:00
|
|
|
/// checkUndefinedButUsed - Check for undefined objects with internal linkage
|
|
|
|
/// or that are inline.
|
|
|
|
static void checkUndefinedButUsed(Sema &S) {
|
|
|
|
if (S.UndefinedButUsed.empty()) return;
|
2013-01-31 11:23:57 +08:00
|
|
|
|
|
|
|
// Collect all the still-undefined entities with internal linkage.
|
|
|
|
SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
|
2013-02-01 16:13:20 +08:00
|
|
|
S.getUndefinedButUsed(Undefined);
|
2013-01-31 11:23:57 +08:00
|
|
|
if (Undefined.empty()) return;
|
|
|
|
|
2017-09-20 15:22:00 +08:00
|
|
|
for (auto Undef : Undefined) {
|
|
|
|
ValueDecl *VD = cast<ValueDecl>(Undef.first);
|
|
|
|
SourceLocation UseLoc = Undef.second;
|
|
|
|
|
|
|
|
if (S.isExternalWithNoLinkageType(VD)) {
|
|
|
|
// C++ [basic.link]p8:
|
|
|
|
// A type without linkage shall not be used as the type of a variable
|
|
|
|
// or function with external linkage unless
|
|
|
|
// -- the entity has C language linkage
|
|
|
|
// -- the entity is not odr-used or is defined in the same TU
|
|
|
|
//
|
|
|
|
// As an extension, accept this in cases where the type is externally
|
|
|
|
// visible, since the function or variable actually can be defined in
|
|
|
|
// another translation unit in that case.
|
|
|
|
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()) {
|
|
|
|
// FIXME: We can promote this to an error. The function or variable can't
|
|
|
|
// be defined anywhere else, so the program must necessarily violate the
|
|
|
|
// one definition rule.
|
|
|
|
S.Diag(VD->getLocation(), diag::warn_undefined_internal)
|
|
|
|
<< isa<VarDecl>(VD) << VD;
|
|
|
|
} else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
|
2016-06-26 00:40:53 +08:00
|
|
|
(void)FD;
|
2016-06-25 08:15:56 +08:00
|
|
|
assert(FD->getMostRecentDecl()->isInlined() &&
|
2013-02-01 16:13:20 +08:00
|
|
|
"used object requires definition but isn't inline or internal?");
|
2016-06-25 08:15:56 +08:00
|
|
|
// FIXME: This is ill-formed; we should reject.
|
2017-09-20 15:22:00 +08:00
|
|
|
S.Diag(VD->getLocation(), diag::warn_undefined_inline) << VD;
|
2016-06-25 08:15:56 +08:00
|
|
|
} else {
|
2017-09-20 15:22:00 +08:00
|
|
|
assert(cast<VarDecl>(VD)->getMostRecentDecl()->isInline() &&
|
2016-06-25 08:15:56 +08:00
|
|
|
"used var requires definition but isn't inline or internal?");
|
2017-09-20 15:22:00 +08:00
|
|
|
S.Diag(VD->getLocation(), diag::err_undefined_inline_var) << VD;
|
2013-02-01 16:13:20 +08:00
|
|
|
}
|
2017-09-20 15:22:00 +08:00
|
|
|
if (UseLoc.isValid())
|
|
|
|
S.Diag(UseLoc, diag::note_used_here);
|
2011-02-19 10:53:41 +08:00
|
|
|
}
|
2016-03-26 05:49:43 +08:00
|
|
|
|
|
|
|
S.UndefinedButUsed.clear();
|
2011-02-19 10:53:41 +08:00
|
|
|
}
|
|
|
|
|
2011-07-29 02:09:57 +08:00
|
|
|
void Sema::LoadExternalWeakUndeclaredIdentifiers() {
|
|
|
|
if (!ExternalSource)
|
|
|
|
return;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-07-29 02:09:57 +08:00
|
|
|
SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
|
|
|
|
ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
|
2015-03-26 16:32:49 +08:00
|
|
|
for (auto &WeakID : WeakIDs)
|
|
|
|
WeakUndeclaredIdentifiers.insert(WeakID);
|
2011-07-29 02:09:57 +08:00
|
|
|
}
|
|
|
|
|
2012-06-06 16:32:04 +08:00
|
|
|
|
|
|
|
typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns true, if all methods and nested classes of the given
|
2012-06-06 16:32:04 +08:00
|
|
|
/// CXXRecordDecl are defined in this translation unit.
|
|
|
|
///
|
|
|
|
/// Should only be called from ActOnEndOfTranslationUnit so that all
|
|
|
|
/// definitions are actually read.
|
|
|
|
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))
|
2017-11-01 12:52:12 +08:00
|
|
|
Complete = M->isDefined() || M->isDefaulted() ||
|
|
|
|
(M->isPure() && !isa<CXXDestructorDecl>(M));
|
2012-06-15 04:56:06 +08:00
|
|
|
else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
|
2015-06-19 04:09:49 +08:00
|
|
|
// If the template function is marked as late template parsed at this
|
|
|
|
// point, it has not been instantiated and therefore we have not
|
|
|
|
// performed semantic analysis on it yet, so we cannot know if the type
|
|
|
|
// can be considered complete.
|
2014-10-11 08:24:15 +08:00
|
|
|
Complete = !F->getTemplatedDecl()->isLateTemplateParsed() &&
|
|
|
|
F->getTemplatedDecl()->isDefined();
|
2012-06-06 16:32:04 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns true, if the given CXXRecordDecl is fully defined in this
|
2012-06-06 16:32:04 +08:00
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
/// Should only be called from ActOnEndOfTranslationUnit so that all
|
|
|
|
/// definitions are actually read.
|
|
|
|
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) {
|
|
|
|
// Check if friend classes and methods are complete.
|
|
|
|
if (TypeSourceInfo *TSI = (*I)->getFriendType()) {
|
|
|
|
// Friend classes are available as the TypeSourceInfo of the FriendDecl.
|
|
|
|
if (CXXRecordDecl *FriendD = TSI->getType()->getAsCXXRecordDecl())
|
|
|
|
Complete = MethodsAndNestedClassesComplete(FriendD, MNCComplete);
|
|
|
|
else
|
|
|
|
Complete = false;
|
|
|
|
} else {
|
|
|
|
// Friend functions are available through the NamedDecl of FriendDecl.
|
|
|
|
if (const FunctionDecl *FD =
|
|
|
|
dyn_cast<FunctionDecl>((*I)->getFriendDecl()))
|
|
|
|
Complete = FD->isDefined();
|
|
|
|
else
|
|
|
|
// This is a template friend, give up.
|
|
|
|
Complete = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RecordsComplete[RD] = Complete;
|
|
|
|
return Complete;
|
|
|
|
}
|
|
|
|
|
Add -Wunused-local-typedef, a warning that finds unused local typedefs.
The warning warns on TypedefNameDecls -- typedefs and C++11 using aliases --
that are !isReferenced(). Since the isReferenced() bit on TypedefNameDecls
wasn't used for anything before this warning it wasn't always set correctly,
so this patch also adds a few missing MarkAnyDeclReferenced() calls in
various places for TypedefNameDecls.
This is made a bit complicated due to local typedefs possibly being used only
after their local scope has closed. Consider:
template <class T>
void template_fun(T t) {
typename T::Foo s3foo; // YYY
(void)s3foo;
}
void template_fun_user() {
struct Local {
typedef int Foo; // XXX
} p;
template_fun(p);
}
Here the typedef in XXX is only used at end-of-translation unit, when YYY in
template_fun() gets instantiated. To handle this, typedefs that are unused when
their scope exits are added to a set of potentially unused typedefs, and that
set gets checked at end-of-TU. Typedefs that are still unused at that point then
get warned on. There's also serialization code for this set, so that the
warning works with precompiled headers and modules. For modules, the warning
is emitted when the module is built, for precompiled headers each time the
header gets used.
Finally, consider a function using C++14 auto return types to return a local
type defined in a header:
auto f() {
struct S { typedef int a; };
return S();
}
Here, the typedef escapes its local scope and could be used by only some
translation units including the header. To not warn on this, add a
RecursiveASTVisitor that marks all delcs on local types returned from auto
functions as referenced. (Except if it's a function with internal linkage, or
the decls are private and the local type has no friends -- in these cases, it
_is_ safe to warn.)
Several of the included testcases (most of the interesting ones) were provided
by Richard Smith.
(gcc's spelling -Wunused-local-typedefs is supported as an alias for this
warning.)
llvm-svn: 217298
2014-09-06 09:25:55 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-07-05 09:42:07 +08:00
|
|
|
/// This is called before the very first declaration in the translation unit
|
|
|
|
/// is parsed. Note that the ASTContext may have already injected some
|
|
|
|
/// declarations.
|
|
|
|
void Sema::ActOnStartOfTranslationUnit() {
|
2018-09-15 09:59:39 +08:00
|
|
|
if (getLangOpts().ModulesTS &&
|
|
|
|
(getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface ||
|
|
|
|
getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
|
2019-04-14 16:06:59 +08:00
|
|
|
// We start in an implied global module fragment.
|
2017-09-04 13:37:53 +08:00
|
|
|
SourceLocation StartOfTU =
|
|
|
|
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
|
2019-04-14 16:06:59 +08:00
|
|
|
ActOnGlobalModuleFragmentDecl(StartOfTU);
|
|
|
|
ModuleScopes.back().ImplicitGlobalModuleFragment = true;
|
2017-07-05 09:42:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-19 05:12:54 +08:00
|
|
|
void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
|
|
|
|
// No explicit actions are required at the end of the global module fragment.
|
|
|
|
if (Kind == TUFragmentKind::Global)
|
2012-08-18 06:17:36 +08:00
|
|
|
return;
|
|
|
|
|
2018-03-27 02:22:47 +08:00
|
|
|
// Transfer late parsed template instantiations over to the pending template
|
2019-04-19 05:12:54 +08:00
|
|
|
// instantiation list. During normal compilation, the late template parser
|
2018-03-27 02:22:47 +08:00
|
|
|
// 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();
|
|
|
|
|
2019-04-19 05:12:54 +08:00
|
|
|
// If DefinedUsedVTables ends up marking any virtual member functions it
|
|
|
|
// might lead to more pending template instantiations, which we then need
|
|
|
|
// to instantiate.
|
|
|
|
DefineUsedVTables();
|
|
|
|
|
|
|
|
// C++: Perform implicit template instantiations.
|
|
|
|
//
|
|
|
|
// FIXME: When we perform these implicit instantiations, we do not
|
|
|
|
// carefully keep track of the point of instantiation (C++ [temp.point]).
|
|
|
|
// This means that name lookup that occurs within the template
|
|
|
|
// instantiation will always happen at the end of the translation unit,
|
|
|
|
// so it will find some names that are not required to be found. This is
|
|
|
|
// valid, but we could do better by diagnosing if an instantiation uses a
|
|
|
|
// name that was not visible at its first point of instantiation.
|
|
|
|
if (ExternalSource) {
|
|
|
|
// Load pending instantiations from the external source.
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-12-11 19:49:42 +08:00
|
|
|
llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
|
2019-04-19 05:12:54 +08:00
|
|
|
PerformPendingInstantiations();
|
|
|
|
}
|
|
|
|
|
2020-02-26 23:57:39 +08:00
|
|
|
emitDeferredDiags();
|
2019-08-24 00:11:14 +08:00
|
|
|
|
2019-04-19 05:12:54 +08:00
|
|
|
assert(LateParsedInstantiations.empty() &&
|
|
|
|
"end of TU template instantiation should not create more "
|
|
|
|
"late-parsed templates");
|
[Sema] Emit diagnostics for uncorrected delayed typos at the end of TU
Summary:
Instead of asserting all typos are corrected in the sema destructor.
The sema destructor is not run in the common case of running the compiler
with the -disable-free cc1 flag (which is the default in the driver).
Having this assertion led to crashes in libclang and clangd, which are not
reproducible when running the compiler.
Asserting at the end of the TU could be an option, but finding all
missing typo correction cases is hard and having worse diagnostics instead
of a failing assertion is a better trade-off.
For more discussion on this, see:
https://lists.llvm.org/pipermail/cfe-dev/2019-July/062872.html
Reviewers: sammccall, rsmith
Reviewed By: rsmith
Subscribers: usaxena95, dgoldman, jkorous, vsapsai, rnk, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64799
llvm-svn: 374152
2019-10-09 18:00:05 +08:00
|
|
|
|
|
|
|
// Report diagnostics for uncorrected delayed typos. Ideally all of them
|
|
|
|
// should have been corrected by that time, but it is very hard to cover all
|
|
|
|
// cases in practice.
|
|
|
|
for (const auto &Typo : DelayedTypos) {
|
|
|
|
// We pass an empty TypoCorrection to indicate no correction was performed.
|
|
|
|
Typo.second.DiagHandler(TypoCorrection());
|
|
|
|
}
|
|
|
|
DelayedTypos.clear();
|
2019-04-19 05:12:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnEndOfTranslationUnit - This is called at the very end of the
|
|
|
|
/// translation unit when EOF is reached and all but the top-level scope is
|
|
|
|
/// popped.
|
|
|
|
void Sema::ActOnEndOfTranslationUnit() {
|
|
|
|
assert(DelayedDiagnostics.getCurrentPool() == nullptr
|
|
|
|
&& "reached end of translation unit with a pool attached?");
|
|
|
|
|
|
|
|
// If code completion is enabled, don't perform any end-of-translation-unit
|
|
|
|
// work.
|
|
|
|
if (PP.isCodeCompletionEnabled())
|
|
|
|
return;
|
|
|
|
|
When we perform dependent name lookup during template instantiation, it's not
sufficient to only consider names visible at the point of instantiation,
because that may not include names that were visible when the template was
defined. More generally, if the instantiation backtrace goes through a module
M, then every declaration visible within M should be available to the
instantiation. Any of those declarations might be part of the interface that M
intended to export to a template that it instantiates.
The fix here has two parts:
1) If we find a non-visible declaration during name lookup during template
instantiation, check whether the declaration was visible from the defining
module of all entities on the active template instantiation stack. The defining
module is not the owning module in all cases: we look at the module in which a
template was defined, not the module in which it was first instantiated.
2) Perform pending instantiations at the end of a module, not at the end of the
translation unit. This is general goodness, since it significantly cuts down
the amount of redundant work that is performed in every TU importing a module,
and also implicitly adds the module containing the point of instantiation to
the set of modules checked for declarations in a lookup within a template
instantiation.
There's a known issue here with template instantiations performed while
building a module, if additional imports are added later on. I'll fix that
in a subsequent commit.
llvm-svn: 187167
2013-07-26 07:08:39 +08:00
|
|
|
// Complete translation units and modules define vtables and perform implicit
|
|
|
|
// instantiations. PCH files do not.
|
|
|
|
if (TUKind != TU_Prefix) {
|
2012-02-08 00:50:53 +08:00
|
|
|
DiagnoseUseOfUnimplementedSelectors();
|
|
|
|
|
2019-04-19 05:12:54 +08:00
|
|
|
ActOnEndOfTranslationUnitFragment(
|
|
|
|
!ModuleScopes.empty() && ModuleScopes.back().Module->Kind ==
|
|
|
|
Module::PrivateModuleFragment
|
|
|
|
? TUFragmentKind::Private
|
|
|
|
: TUFragmentKind::Normal);
|
2018-03-27 02:22:47 +08:00
|
|
|
|
2014-10-23 01:50:19 +08:00
|
|
|
if (LateTemplateParserCleanup)
|
|
|
|
LateTemplateParserCleanup(OpaqueParser);
|
|
|
|
|
2013-10-18 13:54:19 +08:00
|
|
|
CheckDelayedMemberExceptionSpecs();
|
2019-04-19 05:12:54 +08:00
|
|
|
} else {
|
|
|
|
// If we are building a TU prefix for serialization, it is 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();
|
2020-04-19 23:49:47 +08:00
|
|
|
|
|
|
|
if (LangOpts.PCHInstantiateTemplates) {
|
|
|
|
llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
|
|
|
|
PerformPendingInstantiations();
|
|
|
|
}
|
2010-11-25 08:35:20 +08:00
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2021-01-08 06:16:33 +08:00
|
|
|
DiagnoseUnterminatedPragmaAlignPack();
|
2017-04-18 22:33:39 +08:00
|
|
|
DiagnoseUnterminatedPragmaAttribute();
|
|
|
|
|
2013-10-18 13:54:19 +08:00
|
|
|
// All delayed member exception specs should be checked or we end up accepting
|
|
|
|
// incompatible declarations.
|
2018-09-06 06:30:37 +08:00
|
|
|
assert(DelayedOverridingExceptionSpecChecks.empty());
|
|
|
|
assert(DelayedEquivalentExceptionSpecChecks.empty());
|
2013-10-18 13:54:19 +08:00
|
|
|
|
2015-08-15 09:18:16 +08:00
|
|
|
// All dllexport classes should have been processed already.
|
|
|
|
assert(DelayedDllExportClasses.empty());
|
2019-08-01 16:01:09 +08:00
|
|
|
assert(DelayedDllExportMemberFunctions.empty());
|
2015-08-15 09:18:16 +08:00
|
|
|
|
2010-08-14 02:42:17 +08:00
|
|
|
// Remove file scoped decls that turned out to be used.
|
2013-04-30 14:43:16 +08:00
|
|
|
UnusedFileScopedDecls.erase(
|
2014-05-26 14:22:03 +08:00
|
|
|
std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
|
2013-04-30 14:43:16 +08:00
|
|
|
UnusedFileScopedDecls.end(),
|
2017-03-24 07:17:58 +08:00
|
|
|
[this](const DeclaratorDecl *DD) {
|
|
|
|
return ShouldRemoveFromUnused(this, DD);
|
|
|
|
}),
|
2013-04-30 14:43:16 +08:00
|
|
|
UnusedFileScopedDecls.end());
|
2010-04-10 01:41:13 +08:00
|
|
|
|
2011-08-26 06:30:56 +08:00
|
|
|
if (TUKind == TU_Prefix) {
|
|
|
|
// Translation unit prefixes don't need any of the checking below.
|
2016-10-17 18:15:25 +08:00
|
|
|
if (!PP.isIncrementalProcessingEnabled())
|
|
|
|
TUScope = nullptr;
|
2010-08-05 17:48:08 +08:00
|
|
|
return;
|
2010-08-14 06:48:40 +08:00
|
|
|
}
|
2010-08-05 17:48:08 +08:00
|
|
|
|
2009-09-09 02:19:27 +08:00
|
|
|
// Check for #pragma weak identifiers that were never declared
|
2011-07-29 02:09:57 +08:00
|
|
|
LoadExternalWeakUndeclaredIdentifiers();
|
2015-03-26 16:32:49 +08:00
|
|
|
for (auto WeakID : WeakUndeclaredIdentifiers) {
|
|
|
|
if (WeakID.second.getUsed())
|
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2015-09-18 15:40:22 +08:00
|
|
|
Decl *PrevDecl = LookupSingleName(TUScope, WeakID.first, SourceLocation(),
|
|
|
|
LookupOrdinaryName);
|
|
|
|
if (PrevDecl != nullptr &&
|
|
|
|
!(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
|
|
|
|
Diag(WeakID.second.getLocation(), diag::warn_attribute_wrong_decl_type)
|
|
|
|
<< "'weak'" << ExpectedVariableOrFunction;
|
|
|
|
else
|
|
|
|
Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
|
|
|
|
<< WeakID.first;
|
2009-07-30 11:15:39 +08:00
|
|
|
}
|
|
|
|
|
2013-03-14 12:44:56 +08:00
|
|
|
if (LangOpts.CPlusPlus11 &&
|
2014-06-16 07:30:39 +08:00
|
|
|
!Diags.isIgnored(diag::warn_delegating_ctor_cycle, SourceLocation()))
|
2013-03-14 12:44:56 +08:00
|
|
|
CheckDelegatingCtorCycles();
|
|
|
|
|
2016-03-26 05:49:43 +08:00
|
|
|
if (!Diags.hasErrorOccurred()) {
|
|
|
|
if (ExternalSource)
|
|
|
|
ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
|
|
|
|
checkUndefinedButUsed(*this);
|
|
|
|
}
|
|
|
|
|
2019-04-14 16:06:59 +08:00
|
|
|
// A global-module-fragment is only permitted within a module unit.
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-08-26 06:30:56 +08:00
|
|
|
if (TUKind == TU_Module) {
|
2017-10-11 08:36:56 +08:00
|
|
|
// If we are building a module interface unit, we need to have seen the
|
|
|
|
// module declaration by now.
|
|
|
|
if (getLangOpts().getCompilingModule() ==
|
|
|
|
LangOptions::CMK_ModuleInterface &&
|
2018-09-15 09:21:15 +08:00
|
|
|
(ModuleScopes.empty() ||
|
2019-04-19 05:12:54 +08:00
|
|
|
!ModuleScopes.back().Module->isModulePurview()) &&
|
2019-04-14 16:06:59 +08:00
|
|
|
!DiagnosedMissingModuleDeclaration) {
|
2017-10-11 08:36:56 +08:00
|
|
|
// FIXME: Make a better guess as to where to put the module declaration.
|
|
|
|
Diag(getSourceManager().getLocForStartOfFile(
|
|
|
|
getSourceManager().getMainFileID()),
|
|
|
|
diag::err_module_declaration_missing);
|
|
|
|
}
|
|
|
|
|
2011-12-02 09:47:07 +08:00
|
|
|
// If we are building a module, resolve all of the exported declarations
|
|
|
|
// now.
|
|
|
|
if (Module *CurrentModule = PP.getCurrentModule()) {
|
|
|
|
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallVector<Module *, 2> Stack;
|
2011-12-02 09:47:07 +08:00
|
|
|
Stack.push_back(CurrentModule);
|
|
|
|
while (!Stack.empty()) {
|
2013-08-24 00:11:15 +08:00
|
|
|
Module *Mod = Stack.pop_back_val();
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2013-03-21 05:10:35 +08:00
|
|
|
// Resolve the exported declarations and conflicts.
|
2011-12-02 09:47:07 +08:00
|
|
|
// FIXME: Actually complain, once we figure out how to teach the
|
2013-03-21 05:10:35 +08:00
|
|
|
// diagnostic client to deal with complaints in the module map at this
|
2011-12-02 09:47:07 +08:00
|
|
|
// point.
|
|
|
|
ModMap.resolveExports(Mod, /*Complain=*/false);
|
2013-09-24 17:14:14 +08:00
|
|
|
ModMap.resolveUses(Mod, /*Complain=*/false);
|
2013-03-21 05:10:35 +08:00
|
|
|
ModMap.resolveConflicts(Mod, /*Complain=*/false);
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-12-02 09:47:07 +08:00
|
|
|
// Queue the submodules, so their exports will also be resolved.
|
2015-06-12 23:31:50 +08:00
|
|
|
Stack.append(Mod->submodule_begin(), Mod->submodule_end());
|
2011-12-02 09:47:07 +08:00
|
|
|
}
|
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
Add -Wunused-local-typedef, a warning that finds unused local typedefs.
The warning warns on TypedefNameDecls -- typedefs and C++11 using aliases --
that are !isReferenced(). Since the isReferenced() bit on TypedefNameDecls
wasn't used for anything before this warning it wasn't always set correctly,
so this patch also adds a few missing MarkAnyDeclReferenced() calls in
various places for TypedefNameDecls.
This is made a bit complicated due to local typedefs possibly being used only
after their local scope has closed. Consider:
template <class T>
void template_fun(T t) {
typename T::Foo s3foo; // YYY
(void)s3foo;
}
void template_fun_user() {
struct Local {
typedef int Foo; // XXX
} p;
template_fun(p);
}
Here the typedef in XXX is only used at end-of-translation unit, when YYY in
template_fun() gets instantiated. To handle this, typedefs that are unused when
their scope exits are added to a set of potentially unused typedefs, and that
set gets checked at end-of-TU. Typedefs that are still unused at that point then
get warned on. There's also serialization code for this set, so that the
warning works with precompiled headers and modules. For modules, the warning
is emitted when the module is built, for precompiled headers each time the
header gets used.
Finally, consider a function using C++14 auto return types to return a local
type defined in a header:
auto f() {
struct S { typedef int a; };
return S();
}
Here, the typedef escapes its local scope and could be used by only some
translation units including the header. To not warn on this, add a
RecursiveASTVisitor that marks all delcs on local types returned from auto
functions as referenced. (Except if it's a function with internal linkage, or
the decls are private and the local type has no friends -- in these cases, it
_is_ safe to warn.)
Several of the included testcases (most of the interesting ones) were provided
by Richard Smith.
(gcc's spelling -Wunused-local-typedefs is supported as an alias for this
warning.)
llvm-svn: 217298
2014-09-06 09:25:55 +08:00
|
|
|
// Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
|
|
|
|
// modules when they are built, not every time they are used.
|
|
|
|
emitAndClearUnusedLocalTypedefWarnings();
|
2011-08-26 06:30:56 +08:00
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2009-03-11 07:43:53 +08:00
|
|
|
// C99 6.9.2p2:
|
|
|
|
// A declaration of an identifier for an object that has file
|
|
|
|
// scope without an initializer, and without a storage-class
|
|
|
|
// specifier or with the storage-class specifier static,
|
|
|
|
// constitutes a tentative definition. If a translation unit
|
|
|
|
// contains one or more tentative definitions for an identifier,
|
|
|
|
// and the translation unit contains no external definition for
|
|
|
|
// that identifier, then the behavior is exactly as if the
|
|
|
|
// translation unit contains a file scope declaration of that
|
|
|
|
// identifier, with the composite type as of the end of the
|
|
|
|
// translation unit, with an initializer equal to 0.
|
2010-02-01 06:27:38 +08:00
|
|
|
llvm::SmallSet<VarDecl *, 32> Seen;
|
2013-01-20 09:04:14 +08:00
|
|
|
for (TentativeDefinitionsType::iterator
|
2011-07-28 04:58:46 +08:00
|
|
|
T = TentativeDefinitions.begin(ExternalSource),
|
|
|
|
TEnd = TentativeDefinitions.end();
|
2018-06-28 09:57:04 +08:00
|
|
|
T != TEnd; ++T) {
|
2011-07-28 04:58:46 +08:00
|
|
|
VarDecl *VD = (*T)->getActingDefinition();
|
2010-02-01 06:27:38 +08:00
|
|
|
|
|
|
|
// If the tentative definition was completed, getActingDefinition() returns
|
|
|
|
// null. If we've already seen this variable before, insert()'s second
|
|
|
|
// return value is false.
|
2014-11-19 15:49:47 +08:00
|
|
|
if (!VD || VD->isInvalidDecl() || !Seen.insert(VD).second)
|
2009-04-22 01:11:58 +08:00
|
|
|
continue;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const IncompleteArrayType *ArrayT
|
2009-04-22 01:11:58 +08:00
|
|
|
= Context.getAsIncompleteArrayType(VD->getType())) {
|
2009-09-09 02:19:27 +08:00
|
|
|
// Set the length of the array to 1 (C99 6.9.2p5).
|
|
|
|
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
|
|
|
|
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
|
2019-10-04 09:25:59 +08:00
|
|
|
QualType T = Context.getConstantArrayType(ArrayT->getElementType(), One,
|
|
|
|
nullptr, ArrayType::Normal, 0);
|
2009-09-09 02:19:27 +08:00
|
|
|
VD->setType(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
|
2009-04-22 01:11:58 +08:00
|
|
|
diag::err_tentative_def_incomplete_type))
|
|
|
|
VD->setInvalidDecl();
|
|
|
|
|
2016-08-12 06:25:46 +08:00
|
|
|
// No initialization is performed for a tentative definition.
|
2016-08-12 09:55:21 +08:00
|
|
|
CheckCompleteVariableDeclaration(VD);
|
2012-10-24 04:19:32 +08:00
|
|
|
|
2009-04-22 01:11:58 +08:00
|
|
|
// Notify the consumer that we've completed a tentative definition.
|
|
|
|
if (!VD->isInvalidDecl())
|
|
|
|
Consumer.CompleteTentativeDefinition(VD);
|
2009-03-11 07:43:53 +08:00
|
|
|
}
|
2011-01-31 15:04:37 +08:00
|
|
|
|
2019-11-23 00:45:37 +08:00
|
|
|
for (auto D : ExternalDeclarations) {
|
|
|
|
if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Consumer.CompleteExternalDeclaration(D);
|
|
|
|
}
|
|
|
|
|
2011-01-31 15:04:37 +08:00
|
|
|
// If there were errors, disable 'unused' warnings since they will mostly be
|
2018-06-28 09:57:04 +08:00
|
|
|
// 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) {
|
2011-01-31 15:04:37 +08:00
|
|
|
// Output warning for unused file scoped decls.
|
2011-07-28 05:45:57 +08:00
|
|
|
for (UnusedFileScopedDeclsType::iterator
|
|
|
|
I = UnusedFileScopedDecls.begin(ExternalSource),
|
2011-01-31 15:04:37 +08:00
|
|
|
E = UnusedFileScopedDecls.end(); I != E; ++I) {
|
2011-07-28 05:45:57 +08:00
|
|
|
if (ShouldRemoveFromUnused(this, *I))
|
|
|
|
continue;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-01-31 15:04:37 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
|
|
|
|
const FunctionDecl *DiagD;
|
|
|
|
if (!FD->hasBody(DiagD))
|
|
|
|
DiagD = FD;
|
2011-03-04 01:47:42 +08:00
|
|
|
if (DiagD->isDeleted())
|
|
|
|
continue; // Deleted functions are supposed to be unused.
|
2011-04-20 03:51:10 +08:00
|
|
|
if (DiagD->isReferenced()) {
|
|
|
|
if (isa<CXXMethodDecl>(DiagD))
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< DiagD;
|
2012-06-28 03:43:29 +08:00
|
|
|
else {
|
2021-01-05 06:17:45 +08:00
|
|
|
if (FD->getStorageClass() == SC_Static &&
|
2012-06-28 03:43:29 +08:00
|
|
|
!FD->isInlineSpecified() &&
|
2013-08-22 08:27:10 +08:00
|
|
|
!SourceMgr.isInMainFile(
|
2021-01-05 06:17:45 +08:00
|
|
|
SourceMgr.getExpansionLoc(FD->getLocation())))
|
2014-07-27 07:20:08 +08:00
|
|
|
Diag(DiagD->getLocation(),
|
|
|
|
diag::warn_unneeded_static_internal_decl)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< DiagD;
|
2012-06-28 03:43:29 +08:00
|
|
|
else
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< /*function*/ 0 << DiagD;
|
2012-06-28 03:43:29 +08:00
|
|
|
}
|
2011-04-20 03:51:10 +08:00
|
|
|
} else {
|
2017-05-09 19:25:41 +08:00
|
|
|
if (FD->getDescribedFunctionTemplate())
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unused_template)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< /*function*/ 0 << DiagD;
|
2017-05-09 19:25:41 +08:00
|
|
|
else
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
|
|
|
|
? diag::warn_unused_member_function
|
2017-05-09 19:25:41 +08:00
|
|
|
: diag::warn_unused_function)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< DiagD;
|
2011-04-20 03:51:10 +08:00
|
|
|
}
|
2011-01-31 15:04:37 +08:00
|
|
|
} else {
|
|
|
|
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
|
|
|
|
if (!DiagD)
|
|
|
|
DiagD = cast<VarDecl>(*I);
|
2011-04-20 03:51:10 +08:00
|
|
|
if (DiagD->isReferenced()) {
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< /*variable*/ 1 << DiagD;
|
2013-09-11 18:37:35 +08:00
|
|
|
} else if (DiagD->getType().isConstQualified()) {
|
2016-10-28 16:28:42 +08:00
|
|
|
const SourceManager &SM = SourceMgr;
|
|
|
|
if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
|
|
|
|
!PP.getLangOpts().IsHeaderFile)
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< DiagD;
|
2013-09-10 11:05:56 +08:00
|
|
|
} else {
|
2017-05-09 19:25:41 +08:00
|
|
|
if (DiagD->getDescribedVarTemplate())
|
|
|
|
Diag(DiagD->getLocation(), diag::warn_unused_template)
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
<< /*variable*/ 1 << DiagD;
|
2017-05-09 19:25:41 +08:00
|
|
|
else
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD;
|
2011-04-20 03:51:10 +08:00
|
|
|
}
|
2011-01-31 15:04:37 +08:00
|
|
|
}
|
2010-08-15 09:15:20 +08:00
|
|
|
}
|
2011-02-19 10:53:41 +08:00
|
|
|
|
Add -Wunused-local-typedef, a warning that finds unused local typedefs.
The warning warns on TypedefNameDecls -- typedefs and C++11 using aliases --
that are !isReferenced(). Since the isReferenced() bit on TypedefNameDecls
wasn't used for anything before this warning it wasn't always set correctly,
so this patch also adds a few missing MarkAnyDeclReferenced() calls in
various places for TypedefNameDecls.
This is made a bit complicated due to local typedefs possibly being used only
after their local scope has closed. Consider:
template <class T>
void template_fun(T t) {
typename T::Foo s3foo; // YYY
(void)s3foo;
}
void template_fun_user() {
struct Local {
typedef int Foo; // XXX
} p;
template_fun(p);
}
Here the typedef in XXX is only used at end-of-translation unit, when YYY in
template_fun() gets instantiated. To handle this, typedefs that are unused when
their scope exits are added to a set of potentially unused typedefs, and that
set gets checked at end-of-TU. Typedefs that are still unused at that point then
get warned on. There's also serialization code for this set, so that the
warning works with precompiled headers and modules. For modules, the warning
is emitted when the module is built, for precompiled headers each time the
header gets used.
Finally, consider a function using C++14 auto return types to return a local
type defined in a header:
auto f() {
struct S { typedef int a; };
return S();
}
Here, the typedef escapes its local scope and could be used by only some
translation units including the header. To not warn on this, add a
RecursiveASTVisitor that marks all delcs on local types returned from auto
functions as referenced. (Except if it's a function with internal linkage, or
the decls are private and the local type has no friends -- in these cases, it
_is_ safe to warn.)
Several of the included testcases (most of the interesting ones) were provided
by Richard Smith.
(gcc's spelling -Wunused-local-typedefs is supported as an alias for this
warning.)
llvm-svn: 217298
2014-09-06 09:25:55 +08:00
|
|
|
emitAndClearUnusedLocalTypedefWarnings();
|
2010-08-14 02:42:17 +08:00
|
|
|
}
|
2010-08-14 06:48:40 +08:00
|
|
|
|
2014-06-16 07:30:39 +08:00
|
|
|
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
|
2018-06-28 09:57:04 +08:00
|
|
|
// FIXME: Load additional unused private field candidates from the external
|
|
|
|
// source.
|
2012-06-06 16:32:04 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:59:11 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-22 04:05:19 +08:00
|
|
|
// Check we've noticed that we're no longer parsing the initializer for every
|
|
|
|
// variable. If we miss cases, then at best we have a performance issue and
|
|
|
|
// at worst a rejects-valid bug.
|
|
|
|
assert(ParsingInitForAutoVars.empty() &&
|
|
|
|
"Didn't unmark var as having its initializer parsed");
|
|
|
|
|
2016-10-17 18:15:25 +08:00
|
|
|
if (!PP.isIncrementalProcessingEnabled())
|
|
|
|
TUScope = nullptr;
|
2008-08-23 11:19:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-10 13:17:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *Sema::getFunctionLevelDeclContext() {
|
2009-12-19 18:53:49 +08:00
|
|
|
DeclContext *DC = CurContext;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-07 12:59:52 +08:00
|
|
|
while (true) {
|
2020-01-18 15:11:43 +08:00
|
|
|
if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC) || isa<CapturedDecl>(DC) ||
|
|
|
|
isa<RequiresExprBodyDecl>(DC)) {
|
2012-01-07 12:59:52 +08:00
|
|
|
DC = DC->getParent();
|
|
|
|
} else if (isa<CXXMethodDecl>(DC) &&
|
2012-02-13 01:34:23 +08:00
|
|
|
cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
|
2012-01-07 12:59:52 +08:00
|
|
|
cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
|
|
|
|
DC = DC->getParent()->getParent();
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-09 01:45:02 +08:00
|
|
|
return DC;
|
|
|
|
}
|
|
|
|
|
2008-12-05 07:50:19 +08:00
|
|
|
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
|
|
|
|
/// to the function decl for the function being parsed. If we're currently
|
|
|
|
/// in a 'block', this returns the containing context.
|
|
|
|
FunctionDecl *Sema::getCurFunctionDecl() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2008-12-05 07:50:19 +08:00
|
|
|
return dyn_cast<FunctionDecl>(DC);
|
|
|
|
}
|
|
|
|
|
2008-08-11 13:35:13 +08:00
|
|
|
ObjCMethodDecl *Sema::getCurMethodDecl() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2013-06-01 05:51:12 +08:00
|
|
|
while (isa<RecordDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
2008-11-18 00:28:52 +08:00
|
|
|
return dyn_cast<ObjCMethodDecl>(DC);
|
2008-08-11 13:35:13 +08:00
|
|
|
}
|
2008-12-05 07:50:19 +08:00
|
|
|
|
|
|
|
NamedDecl *Sema::getCurFunctionOrMethodDecl() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2008-12-05 07:50:19 +08:00
|
|
|
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
|
2009-01-20 09:17:11 +08:00
|
|
|
return cast<NamedDecl>(DC);
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2008-12-05 07:50:19 +08:00
|
|
|
}
|
|
|
|
|
2019-12-03 20:55:50 +08:00
|
|
|
LangAS Sema::getDefaultCXXMethodAddrSpace() const {
|
|
|
|
if (getLangOpts().OpenCL)
|
|
|
|
return LangAS::opencl_generic;
|
|
|
|
return LangAS::Default;
|
|
|
|
}
|
|
|
|
|
2012-03-14 17:49:32 +08:00
|
|
|
void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
|
|
|
|
// FIXME: It doesn't make sense to me that DiagID is an incoming argument here
|
|
|
|
// and yet we also use the current diag ID on the DiagnosticsEngine. This has
|
|
|
|
// been made more painfully obvious by the refactor that introduced this
|
|
|
|
// function, but it is possible that the incoming argument can be
|
2017-02-21 09:17:38 +08:00
|
|
|
// eliminated. If it truly cannot be (for example, there is some reentrancy
|
2012-03-14 17:49:32 +08:00
|
|
|
// issue I am not seeing yet), then there should at least be a clarifying
|
|
|
|
// comment somewhere.
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) {
|
2012-03-14 17:49:32 +08:00
|
|
|
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(
|
|
|
|
Diags.getCurrentDiagID())) {
|
2010-11-19 04:06:41 +08:00
|
|
|
case DiagnosticIDs::SFINAE_Report:
|
2011-10-19 08:07:01 +08:00
|
|
|
// We'll report the diagnostic below.
|
2010-10-13 07:32:35 +08:00
|
|
|
break;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-10-19 08:07:01 +08:00
|
|
|
case DiagnosticIDs::SFINAE_SubstitutionFailure:
|
|
|
|
// Count this failure so that we know that template argument deduction
|
|
|
|
// has failed.
|
2012-03-14 17:49:32 +08:00
|
|
|
++NumSFINAEErrors;
|
2012-05-07 17:03:25 +08:00
|
|
|
|
|
|
|
// Make a copy of this suppressed diagnostic and store it with the
|
|
|
|
// template-deduction information.
|
|
|
|
if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
|
|
|
|
Diagnostic DiagInfo(&Diags);
|
|
|
|
(*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
|
|
|
|
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
|
|
|
|
}
|
|
|
|
|
2019-09-12 20:16:43 +08:00
|
|
|
Diags.setLastDiagnosticIgnored(true);
|
2012-03-14 17:49:32 +08:00
|
|
|
Diags.Clear();
|
2011-10-19 08:07:01 +08:00
|
|
|
return;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2011-10-19 08:07:01 +08:00
|
|
|
case DiagnosticIDs::SFINAE_AccessControl: {
|
2011-05-12 07:45:11 +08:00
|
|
|
// Per C++ Core Issue 1170, access control is part of SFINAE.
|
2012-03-14 02:30:54 +08:00
|
|
|
// Additionally, the AccessCheckingSFINAE flag can be used to temporarily
|
2011-05-12 07:45:11 +08:00
|
|
|
// make access control a part of SFINAE for the purposes of checking
|
|
|
|
// type traits.
|
2013-01-02 19:42:31 +08:00
|
|
|
if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11)
|
2011-01-28 06:31:44 +08:00
|
|
|
break;
|
2011-10-19 08:07:01 +08:00
|
|
|
|
2012-03-14 17:49:32 +08:00
|
|
|
SourceLocation Loc = Diags.getCurrentDiagLoc();
|
2011-10-19 08:07:01 +08:00
|
|
|
|
|
|
|
// Suppress this diagnostic.
|
2012-03-14 17:49:32 +08:00
|
|
|
++NumSFINAEErrors;
|
2012-05-07 17:03:25 +08:00
|
|
|
|
|
|
|
// Make a copy of this suppressed diagnostic and store it with the
|
|
|
|
// template-deduction information.
|
|
|
|
if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
|
|
|
|
Diagnostic DiagInfo(&Diags);
|
|
|
|
(*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
|
|
|
|
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
|
|
|
|
}
|
|
|
|
|
2019-09-12 20:16:43 +08:00
|
|
|
Diags.setLastDiagnosticIgnored(true);
|
2012-03-14 17:49:32 +08:00
|
|
|
Diags.Clear();
|
2011-10-19 08:07:01 +08:00
|
|
|
|
|
|
|
// Now the diagnostic state is clear, produce a C++98 compatibility
|
|
|
|
// warning.
|
2012-03-14 17:49:32 +08:00
|
|
|
Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control);
|
2011-10-19 08:07:01 +08:00
|
|
|
|
|
|
|
// The last diagnostic which Sema produced was ignored. Suppress any
|
|
|
|
// notes attached to it.
|
2019-09-12 20:16:43 +08:00
|
|
|
Diags.setLastDiagnosticIgnored(true);
|
2010-10-13 07:32:35 +08:00
|
|
|
return;
|
2011-10-19 08:07:01 +08:00
|
|
|
}
|
|
|
|
|
2010-11-19 04:06:41 +08:00
|
|
|
case DiagnosticIDs::SFINAE_Suppress:
|
2010-10-13 07:32:35 +08:00
|
|
|
// Make a copy of this suppressed diagnostic and store it with the
|
|
|
|
// template-deduction information;
|
2012-05-07 17:03:25 +08:00
|
|
|
if (*Info) {
|
|
|
|
Diagnostic DiagInfo(&Diags);
|
2011-01-28 06:31:44 +08:00
|
|
|
(*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
|
2012-05-07 17:03:25 +08:00
|
|
|
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Suppress this diagnostic.
|
2019-09-12 20:16:43 +08:00
|
|
|
Diags.setLastDiagnosticIgnored(true);
|
2012-03-14 17:49:32 +08:00
|
|
|
Diags.Clear();
|
2010-10-13 07:32:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2018-05-15 02:41:44 +08:00
|
|
|
// Copy the diagnostic printing policy over the ASTContext printing policy.
|
|
|
|
// TODO: Stop doing that. See: https://reviews.llvm.org/D45093#1090292
|
2012-03-14 17:49:32 +08:00
|
|
|
Context.setPrintingPolicy(getPrintingPolicy());
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2010-10-13 07:32:35 +08:00
|
|
|
// Emit the diagnostic.
|
2012-03-14 17:49:32 +08:00
|
|
|
if (!Diags.EmitCurrentDiagnostic())
|
2009-06-14 15:33:30 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 06:48:49 +08:00
|
|
|
// If this is not a note, and we're in a template instantiation
|
|
|
|
// that is different from the last template instantiation where
|
|
|
|
// we emitted an error, print a template instantiation
|
|
|
|
// backtrace.
|
2017-02-21 09:17:38 +08:00
|
|
|
if (!DiagnosticIDs::isBuiltinNote(DiagID))
|
|
|
|
PrintContextStack();
|
2009-03-21 06:48:49 +08:00
|
|
|
}
|
Add support for retrieving the Doxygen comment associated with a given
declaration in the AST.
The new ASTContext::getCommentForDecl function searches for a comment
that is attached to the given declaration, and returns that comment,
which may be composed of several comment blocks.
Comments are always available in an AST. However, to avoid harming
performance, we don't actually parse the comments. Rather, we keep the
source ranges of all of the comments within a large, sorted vector,
then lazily extract comments via a binary search in that vector only
when needed (which never occurs in a "normal" compile).
Comments are written to a precompiled header/AST file as a blob of
source ranges. That blob is only lazily loaded when one requests a
comment for a declaration (this never occurs in a "normal" compile).
The indexer testbed now supports comment extraction. When the
-point-at location points to a declaration with a Doxygen-style
comment, the indexer testbed prints the associated comment
block(s). See test/Index/comments.c for an example.
Some notes:
- We don't actually attempt to parse the comment blocks themselves,
beyond identifying them as Doxygen comment blocks to associate them
with a declaration.
- We won't find comment blocks that aren't adjacent to the
declaration, because we start our search based on the location of
the declaration.
- We don't go through the necessary hops to find, for example,
whether some redeclaration of a declaration has comments when our
current declaration does not. Similarly, we don't attempt to
associate a \param Foo marker in a function body comment with the
parameter named Foo (although that is certainly possible).
- Verification of my "no performance impact" claims is still "to be
done".
llvm-svn: 74704
2009-07-03 01:08:52 +08:00
|
|
|
|
2009-08-27 06:33:56 +08:00
|
|
|
Sema::SemaDiagnosticBuilder
|
2020-09-24 06:00:23 +08:00
|
|
|
Sema::Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint) {
|
|
|
|
return Diag(Loc, PD.getDiagID(), DeferHint) << PD;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2020-09-24 06:00:23 +08:00
|
|
|
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;
|
2009-08-27 06:33:56 +08:00
|
|
|
}
|
|
|
|
|
2019-02-08 03:46:42 +08:00
|
|
|
// Print notes showing how we can reach FD starting from an a priori
|
|
|
|
// known-callable function.
|
|
|
|
static void emitCallStackNotes(Sema &S, FunctionDecl *FD) {
|
|
|
|
auto FnIt = S.DeviceKnownEmittedFns.find(FD);
|
|
|
|
while (FnIt != S.DeviceKnownEmittedFns.end()) {
|
2020-04-02 11:26:56 +08:00
|
|
|
// Respect error limit.
|
|
|
|
if (S.Diags.hasFatalErrorOccurred())
|
|
|
|
return;
|
2019-02-08 03:46:42 +08:00
|
|
|
DiagnosticBuilder Builder(
|
|
|
|
S.Diags.Report(FnIt->second.Loc, diag::note_called_by));
|
|
|
|
Builder << FnIt->second.FD;
|
|
|
|
FnIt = S.DeviceKnownEmittedFns.find(FnIt->second.FD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-26 23:57:39 +08:00
|
|
|
namespace {
|
2020-04-02 11:26:56 +08:00
|
|
|
|
2020-02-26 23:57:39 +08:00
|
|
|
/// Helper class that emits deferred diagnostic messages if an entity directly
|
|
|
|
/// or indirectly using the function that causes the deferred diagnostic
|
|
|
|
/// messages is known to be emitted.
|
2020-04-02 11:26:56 +08:00
|
|
|
///
|
|
|
|
/// During parsing of AST, certain diagnostic messages are recorded as deferred
|
|
|
|
/// diagnostics since it is unknown whether the functions containing such
|
|
|
|
/// diagnostics will be emitted. A list of potentially emitted functions and
|
|
|
|
/// variables that may potentially trigger emission of functions are also
|
|
|
|
/// recorded. DeferredDiagnosticsEmitter recursively visits used functions
|
|
|
|
/// by each function to emit deferred diagnostics.
|
|
|
|
///
|
|
|
|
/// During the visit, certain OpenMP directives or initializer of variables
|
|
|
|
/// with certain OpenMP attributes will cause subsequent visiting of any
|
|
|
|
/// functions enter a state which is called OpenMP device context in this
|
|
|
|
/// implementation. The state is exited when the directive or initializer is
|
|
|
|
/// exited. This state can change the emission states of subsequent uses
|
|
|
|
/// of functions.
|
|
|
|
///
|
|
|
|
/// Conceptually the functions or variables to be visited form a use graph
|
|
|
|
/// where the parent node uses the child node. At any point of the visit,
|
|
|
|
/// the tree nodes traversed from the tree root to the current node form a use
|
|
|
|
/// stack. The emission state of the current node depends on two factors:
|
|
|
|
/// 1. the emission state of the root node
|
|
|
|
/// 2. whether the current node is in OpenMP device context
|
|
|
|
/// If the function is decided to be emitted, its contained deferred diagnostics
|
|
|
|
/// are emitted, together with the information about the use stack.
|
|
|
|
///
|
2020-02-26 23:57:39 +08:00
|
|
|
class DeferredDiagnosticsEmitter
|
|
|
|
: public UsedDeclVisitor<DeferredDiagnosticsEmitter> {
|
|
|
|
public:
|
|
|
|
typedef UsedDeclVisitor<DeferredDiagnosticsEmitter> Inherited;
|
2020-04-02 11:26:56 +08:00
|
|
|
|
|
|
|
// Whether the function is already in the current use-path.
|
2020-07-20 22:41:44 +08:00
|
|
|
llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> InUsePath;
|
2020-04-02 11:26:56 +08:00
|
|
|
|
|
|
|
// The current use-path.
|
|
|
|
llvm::SmallVector<CanonicalDeclPtr<FunctionDecl>, 4> UsePath;
|
|
|
|
|
|
|
|
// Whether the visiting of the function has been done. Done[0] is for the
|
|
|
|
// case not in OpenMP device context. Done[1] is for the case in OpenMP
|
|
|
|
// device context. We need two sets because diagnostics emission may be
|
|
|
|
// different depending on whether it is in OpenMP device context.
|
2020-07-20 22:41:44 +08:00
|
|
|
llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2];
|
2020-04-02 11:26:56 +08:00
|
|
|
|
|
|
|
// Emission state of the root node of the current use graph.
|
|
|
|
bool ShouldEmitRootNode;
|
|
|
|
|
|
|
|
// Current OpenMP device context level. It is initialized to 0 and each
|
|
|
|
// entering of device context increases it by 1 and each exit decreases
|
|
|
|
// it by 1. Non-zero value indicates it is currently in device context.
|
2020-02-26 23:57:39 +08:00
|
|
|
unsigned InOMPDeviceContext;
|
|
|
|
|
|
|
|
DeferredDiagnosticsEmitter(Sema &S)
|
2020-04-02 11:26:56 +08:00
|
|
|
: Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {}
|
2020-02-26 23:57:39 +08:00
|
|
|
|
|
|
|
void VisitOMPTargetDirective(OMPTargetDirective *Node) {
|
|
|
|
++InOMPDeviceContext;
|
|
|
|
Inherited::VisitOMPTargetDirective(Node);
|
|
|
|
--InOMPDeviceContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
void visitUsedDecl(SourceLocation Loc, Decl *D) {
|
2020-03-28 00:38:20 +08:00
|
|
|
if (isa<VarDecl>(D))
|
|
|
|
return;
|
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(D))
|
|
|
|
checkFunc(Loc, FD);
|
|
|
|
else
|
2020-02-26 23:57:39 +08:00
|
|
|
Inherited::visitUsedDecl(Loc, D);
|
|
|
|
}
|
2020-03-28 00:38:20 +08:00
|
|
|
|
|
|
|
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) {
|
2020-05-21 22:35:14 +08:00
|
|
|
auto &Done = DoneMap[InOMPDeviceContext > 0 ? 1 : 0];
|
2020-04-02 11:26:56 +08:00
|
|
|
FunctionDecl *Caller = UsePath.empty() ? nullptr : UsePath.back();
|
|
|
|
if ((!ShouldEmitRootNode && !S.getLangOpts().OpenMP && !Caller) ||
|
|
|
|
S.shouldIgnoreInHostDeviceCheck(FD) || InUsePath.count(FD))
|
2020-03-28 00:38:20 +08:00
|
|
|
return;
|
|
|
|
// Finalize analysis of OpenMP-specific constructs.
|
2020-08-19 02:51:51 +08:00
|
|
|
if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1 &&
|
|
|
|
(ShouldEmitRootNode || InOMPDeviceContext))
|
2020-03-28 00:38:20 +08:00
|
|
|
S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
|
|
|
|
if (Caller)
|
|
|
|
S.DeviceKnownEmittedFns[FD] = {Caller, Loc};
|
2020-04-02 11:26:56 +08:00
|
|
|
// Always emit deferred diagnostics for the direct users. This does not
|
|
|
|
// lead to explosion of diagnostics since each user is visited at most
|
|
|
|
// twice.
|
|
|
|
if (ShouldEmitRootNode || InOMPDeviceContext)
|
|
|
|
emitDeferredDiags(FD, Caller);
|
|
|
|
// Do not revisit a function if the function body has been completely
|
|
|
|
// visited before.
|
2020-04-07 01:52:47 +08:00
|
|
|
if (!Done.insert(FD).second)
|
2020-04-02 11:26:56 +08:00
|
|
|
return;
|
|
|
|
InUsePath.insert(FD);
|
|
|
|
UsePath.push_back(FD);
|
2020-03-28 00:38:20 +08:00
|
|
|
if (auto *S = FD->getBody()) {
|
|
|
|
this->Visit(S);
|
|
|
|
}
|
2020-04-02 11:26:56 +08:00
|
|
|
UsePath.pop_back();
|
|
|
|
InUsePath.erase(FD);
|
2020-03-28 00:38:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void checkRecordedDecl(Decl *D) {
|
2020-04-02 11:26:56 +08:00
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
ShouldEmitRootNode = S.getEmissionStatus(FD, /*Final=*/true) ==
|
|
|
|
Sema::FunctionEmissionStatus::Emitted;
|
2020-03-28 00:38:20 +08:00
|
|
|
checkFunc(SourceLocation(), FD);
|
2020-04-02 11:26:56 +08:00
|
|
|
} else
|
2020-03-28 00:38:20 +08:00
|
|
|
checkVar(cast<VarDecl>(D));
|
|
|
|
}
|
2020-04-02 11:26:56 +08:00
|
|
|
|
|
|
|
// Emit any deferred diagnostics for FD
|
|
|
|
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) {
|
|
|
|
// Respect error limit.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
// Emit the note on the first diagnostic in case too many diagnostics
|
|
|
|
// cause the note not emitted.
|
|
|
|
if (FirstDiag && HasWarningOrError && ShowCallStack) {
|
|
|
|
emitCallStackNotes(S, FD);
|
|
|
|
FirstDiag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-26 23:57:39 +08:00
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
void Sema::emitDeferredDiags() {
|
|
|
|
if (ExternalSource)
|
|
|
|
ExternalSource->ReadDeclsToCheckForDeferredDiags(
|
|
|
|
DeclsToCheckForDeferredDiags);
|
|
|
|
|
|
|
|
if ((DeviceDeferredDiags.empty() && !LangOpts.OpenMP) ||
|
|
|
|
DeclsToCheckForDeferredDiags.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
DeferredDiagnosticsEmitter DDE(*this);
|
|
|
|
for (auto D : DeclsToCheckForDeferredDiags)
|
2020-03-28 00:38:20 +08:00
|
|
|
DDE.checkRecordedDecl(D);
|
2019-02-08 03:46:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// In CUDA, there are some constructs which may appear in semantically-valid
|
|
|
|
// code, but trigger errors if we ever generate code for the function in which
|
|
|
|
// they appear. Essentially every construct you're not allowed to use on the
|
|
|
|
// device falls into this category, because you are allowed to use these
|
|
|
|
// constructs in a __host__ __device__ function, but only if that function is
|
|
|
|
// never codegen'ed on the device.
|
|
|
|
//
|
|
|
|
// To handle semantic checking for these constructs, we keep track of the set of
|
|
|
|
// functions we know will be emitted, either because we could tell a priori that
|
|
|
|
// they would be emitted, or because they were transitively called by a
|
|
|
|
// known-emitted function.
|
|
|
|
//
|
|
|
|
// We also keep a partial call graph of which not-known-emitted functions call
|
|
|
|
// which other not-known-emitted functions.
|
|
|
|
//
|
|
|
|
// When we see something which is illegal if the current function is emitted
|
|
|
|
// (usually by way of CUDADiagIfDeviceCode, CUDADiagIfHostCode, or
|
|
|
|
// CheckCUDACall), we first check if the current function is known-emitted. If
|
|
|
|
// so, we immediately output the diagnostic.
|
|
|
|
//
|
|
|
|
// Otherwise, we "defer" the diagnostic. It sits in Sema::DeviceDeferredDiags
|
|
|
|
// until we discover that the function is known-emitted, at which point we take
|
|
|
|
// it out of this map and emit the diagnostic.
|
|
|
|
|
2020-09-24 06:00:23 +08:00
|
|
|
Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc,
|
|
|
|
unsigned DiagID,
|
|
|
|
FunctionDecl *Fn, Sema &S)
|
2019-02-08 03:46:42 +08:00
|
|
|
: 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:
|
2020-09-24 06:00:23 +08:00
|
|
|
ImmediateDiag.emplace(
|
|
|
|
ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID));
|
2019-02-08 03:46:42 +08:00
|
|
|
break;
|
|
|
|
case K_Deferred:
|
|
|
|
assert(Fn && "Must have a function to attach the deferred diag to.");
|
2019-02-22 22:42:48 +08:00
|
|
|
auto &Diags = S.DeviceDeferredDiags[Fn];
|
|
|
|
PartialDiagId.emplace(Diags.size());
|
|
|
|
Diags.emplace_back(Loc, S.PDiag(DiagID));
|
2019-02-08 03:46:42 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-24 06:00:23 +08:00
|
|
|
Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D)
|
2019-02-23 04:36:10 +08:00
|
|
|
: S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn),
|
|
|
|
ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag),
|
|
|
|
PartialDiagId(D.PartialDiagId) {
|
|
|
|
// Clean the previous diagnostics.
|
|
|
|
D.ShowCallStack = false;
|
|
|
|
D.ImmediateDiag.reset();
|
|
|
|
D.PartialDiagId.reset();
|
|
|
|
}
|
|
|
|
|
2020-09-24 06:00:23 +08:00
|
|
|
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
|
2019-02-08 03:46:42 +08:00
|
|
|
if (ImmediateDiag) {
|
|
|
|
// Emit our diagnostic and, if it was a warning or error, output a callstack
|
|
|
|
// if Fn isn't a priori known-emitted.
|
|
|
|
bool IsWarningOrError = S.getDiagnostics().getDiagnosticLevel(
|
|
|
|
DiagID, Loc) >= DiagnosticsEngine::Warning;
|
|
|
|
ImmediateDiag.reset(); // Emit the immediate diag.
|
|
|
|
if (IsWarningOrError && ShowCallStack)
|
|
|
|
emitCallStackNotes(S, Fn);
|
2019-02-22 22:42:48 +08:00
|
|
|
} else {
|
|
|
|
assert((!PartialDiagId || ShowCallStack) &&
|
|
|
|
"Must always show call stack for deferred diags.");
|
2019-02-08 03:46:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-29 16:42:20 +08:00
|
|
|
Sema::SemaDiagnosticBuilder
|
|
|
|
Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) {
|
|
|
|
FD = FD ? FD : getCurFunctionDecl();
|
2019-08-24 00:11:14 +08:00
|
|
|
if (LangOpts.OpenMP)
|
2021-01-29 16:42:20 +08:00
|
|
|
return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD)
|
|
|
|
: diagIfOpenMPHostCode(Loc, DiagID, FD);
|
2019-02-22 22:42:48 +08:00
|
|
|
if (getLangOpts().CUDA)
|
|
|
|
return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID)
|
|
|
|
: CUDADiagIfHostCode(Loc, DiagID);
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
|
|
|
|
if (getLangOpts().SYCLIsDevice)
|
|
|
|
return SYCLDiagIfDeviceCode(Loc, DiagID);
|
|
|
|
|
2020-09-24 06:00:23 +08:00
|
|
|
return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID,
|
2021-01-29 16:42:20 +08:00
|
|
|
FD, *this);
|
2020-09-24 06:00:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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 || !IsError);
|
|
|
|
auto SetIsLastErrorImmediate = [&](bool Flag) {
|
|
|
|
if (IsError)
|
|
|
|
IsLastErrorImmediate = Flag;
|
|
|
|
};
|
|
|
|
if (!ShouldDefer) {
|
|
|
|
SetIsLastErrorImmediate(true);
|
|
|
|
return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc,
|
|
|
|
DiagID, getCurFunctionDecl(), *this);
|
|
|
|
}
|
|
|
|
|
2021-01-29 16:42:20 +08:00
|
|
|
SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice
|
|
|
|
? CUDADiagIfDeviceCode(Loc, DiagID)
|
|
|
|
: CUDADiagIfHostCode(Loc, DiagID);
|
2020-09-24 06:00:23 +08:00
|
|
|
SetIsLastErrorImmediate(DB.isImmediate());
|
|
|
|
return DB;
|
2019-02-21 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
2021-01-29 16:42:20 +08:00
|
|
|
void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) {
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
if (isUnevaluatedContext())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Decl *C = cast<Decl>(getCurLexicalContext());
|
|
|
|
|
|
|
|
// Memcpy operations for structs containing a member with unsupported type
|
|
|
|
// are ok, though.
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-01-29 16:42:20 +08:00
|
|
|
// Try to associate errors with the lexical context, if that is a function, or
|
|
|
|
// the value declaration otherwise.
|
|
|
|
FunctionDecl *FD =
|
|
|
|
isa<FunctionDecl>(C) ? cast<FunctionDecl>(C) : dyn_cast<FunctionDecl>(D);
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
auto CheckType = [&](QualType Ty) {
|
2020-05-30 17:27:47 +08:00
|
|
|
if (Ty->isDependentType())
|
|
|
|
return;
|
|
|
|
|
2021-01-21 03:33:22 +08:00
|
|
|
if (Ty->isExtIntType()) {
|
|
|
|
if (!Context.getTargetInfo().hasExtIntType()) {
|
2021-01-29 16:42:20 +08:00
|
|
|
targetDiag(Loc, diag::err_device_unsupported_type, FD)
|
2021-01-21 03:33:22 +08:00
|
|
|
<< D << false /*show bit size*/ << 0 /*bitsize*/
|
|
|
|
<< Ty << Context.getTargetInfo().getTriple().str();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
|
|
|
|
((Ty->isFloat128Type() ||
|
|
|
|
(Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128)) &&
|
|
|
|
!Context.getTargetInfo().hasFloat128Type()) ||
|
|
|
|
(Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
|
|
|
|
!Context.getTargetInfo().hasInt128Type())) {
|
2021-01-29 16:42:20 +08:00
|
|
|
if (targetDiag(Loc, diag::err_device_unsupported_type, FD)
|
2021-01-21 03:33:22 +08:00
|
|
|
<< D << true /*show bit size*/
|
|
|
|
<< static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty
|
2021-01-29 16:42:20 +08:00
|
|
|
<< Context.getTargetInfo().getTriple().str())
|
|
|
|
D->setInvalidDecl();
|
|
|
|
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
QualType Ty = D->getType();
|
|
|
|
CheckType(Ty);
|
|
|
|
|
|
|
|
if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
|
|
|
|
for (const auto &ParamTy : FPTy->param_types())
|
|
|
|
CheckType(ParamTy);
|
|
|
|
CheckType(FPTy->getReturnType());
|
|
|
|
}
|
2021-01-29 16:42:20 +08:00
|
|
|
if (const auto *FNPTy = dyn_cast<FunctionNoProtoType>(Ty))
|
|
|
|
CheckType(FNPTy->getReturnType());
|
[OpenMP][SYCL] Improve diagnosing of unsupported types usage
Summary:
Diagnostic is emitted if some declaration of unsupported type
declaration is used inside device code.
Memcpy operations for structs containing member with unsupported type
are allowed. Fixed crash on attempt to emit diagnostic outside of the
functions.
The approach is generalized between SYCL and OpenMP.
CUDA/OMP deferred diagnostic interface is going to be used for SYCL device.
Reviewers: rsmith, rjmccall, ABataev, erichkeane, bader, jdoerfert, aaron.ballman
Reviewed By: jdoerfert
Subscribers: guansong, sstefan1, yaxunl, mgorny, bader, ebevhan, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74387
2020-05-29 20:41:37 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Looks through the macro-expansion chain for the given
|
2011-07-26 13:40:03 +08:00
|
|
|
/// location, looking for a macro expansion with the given name.
|
2011-03-08 15:59:04 +08:00
|
|
|
/// If one is found, returns true and sets the location to that
|
2011-07-26 13:40:03 +08:00
|
|
|
/// expansion loc.
|
2011-07-23 18:55:15 +08:00
|
|
|
bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
|
2011-03-08 15:59:04 +08:00
|
|
|
SourceLocation loc = locref;
|
|
|
|
if (!loc.isMacroID()) return false;
|
|
|
|
|
|
|
|
// There's no good way right now to look at the intermediate
|
2011-07-26 13:40:03 +08:00
|
|
|
// expansions, so just jump to the expansion location.
|
2011-07-26 00:49:02 +08:00
|
|
|
loc = getSourceManager().getExpansionLoc(loc);
|
2011-03-08 15:59:04 +08:00
|
|
|
|
|
|
|
// If that's written with the name, stop here.
|
2020-11-17 21:02:58 +08:00
|
|
|
SmallString<16> buffer;
|
2011-03-08 15:59:04 +08:00
|
|
|
if (getPreprocessor().getSpelling(loc, buffer) == name) {
|
|
|
|
locref = loc;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determines the active Scope associated with the given declaration
|
2010-07-03 01:43:08 +08:00
|
|
|
/// context.
|
|
|
|
///
|
|
|
|
/// This routine maps a declaration context to the active Scope object that
|
|
|
|
/// represents that declaration context in the parser. It is typically used
|
|
|
|
/// from "scope-less" code (e.g., template instantiation, lazy creation of
|
|
|
|
/// declarations) that injects a name for name-lookup purposes and, therefore,
|
|
|
|
/// must update the Scope.
|
|
|
|
///
|
|
|
|
/// \returns The scope corresponding to the given declaraion context, or NULL
|
|
|
|
/// if no such scope is open.
|
|
|
|
Scope *Sema::getScopeForContext(DeclContext *Ctx) {
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2010-07-03 01:43:08 +08:00
|
|
|
if (!Ctx)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2010-07-03 01:43:08 +08:00
|
|
|
Ctx = Ctx->getPrimaryContext();
|
|
|
|
for (Scope *S = getCurScope(); S; S = S->getParent()) {
|
2010-07-09 07:07:34 +08:00
|
|
|
// Ignore scopes that cannot have declarations. This is important for
|
|
|
|
// out-of-line definitions of static class members.
|
|
|
|
if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
|
2013-10-09 01:08:03 +08:00
|
|
|
if (DeclContext *Entity = S->getEntity())
|
2010-07-09 07:07:34 +08:00
|
|
|
if (Ctx == Entity->getPrimaryContext())
|
|
|
|
return S;
|
2010-07-03 01:43:08 +08:00
|
|
|
}
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2010-07-03 01:43:08 +08:00
|
|
|
}
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Enter a new function scope
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
void Sema::PushFunctionScope() {
|
2019-05-31 08:45:09 +08:00
|
|
|
if (FunctionScopes.empty() && CachedFunctionScope) {
|
|
|
|
// Use CachedFunctionScope to avoid allocating memory when possible.
|
|
|
|
CachedFunctionScope->Clear();
|
|
|
|
FunctionScopes.push_back(CachedFunctionScope.release());
|
2018-03-13 05:43:02 +08:00
|
|
|
} else {
|
|
|
|
FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
}
|
2017-04-26 23:06:24 +08:00
|
|
|
if (LangOpts.OpenMP)
|
|
|
|
pushOpenMPFunctionRegion();
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
|
2010-11-19 08:19:15 +08:00
|
|
|
FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
BlockScope, Block));
|
|
|
|
}
|
|
|
|
|
2013-11-12 09:46:33 +08:00
|
|
|
LambdaScopeInfo *Sema::PushLambdaScope() {
|
2013-11-12 09:40:44 +08:00
|
|
|
LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics());
|
|
|
|
FunctionScopes.push_back(LSI);
|
|
|
|
return LSI;
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
|
|
|
|
if (LambdaScopeInfo *const LSI = getCurLambda()) {
|
|
|
|
LSI->AutoTemplateParameterDepth = Depth;
|
|
|
|
return;
|
2018-03-13 05:43:02 +08:00
|
|
|
}
|
|
|
|
llvm_unreachable(
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
"Remove assertion if intentionally called in a non-lambda context.");
|
2012-01-05 11:35:19 +08:00
|
|
|
}
|
|
|
|
|
2018-10-02 05:51:28 +08:00
|
|
|
// Check that the type of the VarDecl has an accessible copy constructor and
|
2019-04-30 08:19:43 +08:00
|
|
|
// resolve its destructor's exception specification.
|
2018-10-02 05:51:28 +08:00
|
|
|
static void checkEscapingByref(VarDecl *VD, Sema &S) {
|
|
|
|
QualType T = VD->getType();
|
|
|
|
EnterExpressionEvaluationContext scope(
|
|
|
|
S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
|
|
|
SourceLocation Loc = VD->getLocation();
|
2018-12-21 22:10:18 +08:00
|
|
|
Expr *VarRef =
|
|
|
|
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
|
2018-10-02 05:51:28 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2019-04-30 08:19:43 +08:00
|
|
|
// The destructor's exception specification is needed when IRGen generates
|
2018-10-02 05:51:28 +08:00
|
|
|
// 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) {
|
|
|
|
for (const BlockDecl::Capture &BC : BD->captures()) {
|
|
|
|
VarDecl *VD = BC.getVariable();
|
2019-09-07 08:34:43 +08:00
|
|
|
if (VD->hasAttr<BlocksAttr>()) {
|
|
|
|
// Nothing to do if this is a __block variable captured by a
|
|
|
|
// non-escaping block.
|
|
|
|
if (BD->doesNotEscape())
|
|
|
|
continue;
|
2018-10-02 05:51:28 +08:00
|
|
|
VD->setEscapingByref();
|
2019-09-07 08:34:43 +08:00
|
|
|
}
|
|
|
|
// Check whether the captured variable is or contains an object of
|
|
|
|
// non-trivial C union type.
|
|
|
|
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);
|
2018-10-02 05:51:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 08:45:09 +08:00
|
|
|
/// Pop a function (or block or lambda or captured region) scope from the stack.
|
|
|
|
///
|
|
|
|
/// \param WP The warning policy to use for CFG-based warnings, or null if such
|
|
|
|
/// warnings should not be produced.
|
|
|
|
/// \param D The declaration corresponding to this function scope, if producing
|
|
|
|
/// CFG-based warnings.
|
|
|
|
/// \param BlockType The type of the block expression, if D is a BlockDecl.
|
|
|
|
Sema::PoppedFunctionScopePtr
|
|
|
|
Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
|
|
|
|
const Decl *D, QualType BlockType) {
|
2018-03-08 09:12:22 +08:00
|
|
|
assert(!FunctionScopes.empty() && "mismatched push/pop!");
|
2018-10-02 05:51:28 +08:00
|
|
|
|
|
|
|
markEscapingByrefs(*FunctionScopes.back(), *this);
|
|
|
|
|
2019-05-31 08:45:09 +08:00
|
|
|
PoppedFunctionScopePtr Scope(FunctionScopes.pop_back_val(),
|
|
|
|
PoppedFunctionScopeDeleter(this));
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2017-04-26 23:06:24 +08:00
|
|
|
if (LangOpts.OpenMP)
|
2019-05-31 08:45:09 +08:00
|
|
|
popOpenMPFunctionRegion(Scope.get());
|
2017-04-26 23:06:24 +08:00
|
|
|
|
2011-02-23 09:51:48 +08:00
|
|
|
// Issue any analysis-based warnings.
|
|
|
|
if (WP && D)
|
2019-05-31 08:45:09 +08:00
|
|
|
AnalysisWarnings.IssueWarnings(*WP, Scope.get(), D, BlockType);
|
2014-05-16 04:58:55 +08:00
|
|
|
else
|
|
|
|
for (const auto &PUD : Scope->PossiblyUnreachableDiags)
|
|
|
|
Diag(PUD.Loc, PUD.PD);
|
2011-02-23 09:51:48 +08:00
|
|
|
|
2019-05-31 08:45:09 +08:00
|
|
|
return Scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::PoppedFunctionScopeDeleter::
|
|
|
|
operator()(sema::FunctionScopeInfo *Scope) const {
|
|
|
|
// Stash the function scope for later reuse if it's for a normal function.
|
|
|
|
if (Scope->isPlainFunction() && !Self->CachedFunctionScope)
|
|
|
|
Self->CachedFunctionScope.reset(Scope);
|
|
|
|
else
|
2010-08-25 16:40:02 +08:00
|
|
|
delete Scope;
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
}
|
|
|
|
|
2018-02-03 08:44:57 +08:00
|
|
|
void Sema::PushCompoundScope(bool IsStmtExpr) {
|
|
|
|
getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo(IsStmtExpr));
|
2012-02-15 06:14:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::PopCompoundScope() {
|
|
|
|
FunctionScopeInfo *CurFunction = getCurFunction();
|
|
|
|
assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop");
|
|
|
|
|
|
|
|
CurFunction->CompoundScopes.pop_back();
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determine whether any errors occurred within this function/method/
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
/// block.
|
2011-06-16 07:02:42 +08:00
|
|
|
bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
|
2020-06-09 05:04:54 +08:00
|
|
|
return getCurFunction()->hasUnrecoverableErrorOccurred();
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
}
|
|
|
|
|
2018-03-13 05:43:02 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2021-04-16 07:49:19 +08:00
|
|
|
void Sema::setFunctionHasMustTail() {
|
|
|
|
if (!FunctionScopes.empty())
|
|
|
|
FunctionScopes.back()->setHasMustTail();
|
|
|
|
}
|
|
|
|
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
BlockScopeInfo *Sema::getCurBlock() {
|
|
|
|
if (FunctionScopes.empty())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2014-04-27 02:29:13 +08:00
|
|
|
auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
|
|
|
|
if (CurBSI && CurBSI->TheDecl &&
|
|
|
|
!CurBSI->TheDecl->Encloses(CurContext)) {
|
|
|
|
// We have switched contexts due to template instantiation.
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty());
|
2014-04-27 02:29:13 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CurBSI;
|
Keep an explicit stack of function and block scopes, each element of
which has the label map, switch statement stack, etc. Previously, we
had a single set of maps in Sema (for the function) along with a stack
of block scopes. However, this lead to funky behavior with nested
functions, e.g., in the member functions of local classes.
The explicit-stack approach is far cleaner, and we retain a 1-element
cache so that we're not malloc/free'ing every time we enter a
function. Fixes PR6382.
Also, tweaked the unused-variable warning suppression logic to look at
errors within a given Scope rather than within a given function. The
prior code wasn't looking at the right number-of-errors count when
dealing with blocks, since the block's count would be deallocated
before we got to ActOnPopScope. This approach works with nested
blocks/functions, and gives tighter error recovery.
llvm-svn: 97518
2010-03-02 07:15:13 +08:00
|
|
|
}
|
2010-06-01 17:23:16 +08:00
|
|
|
|
2018-03-08 06:48:35 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-08-27 06:51:28 +08:00
|
|
|
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)) {
|
|
|
|
// We have switched contexts due to template instantiation.
|
|
|
|
// FIXME: We should swap out the FunctionScopes during code synthesis
|
|
|
|
// so that we don't need to check for this.
|
|
|
|
assert(!CodeSynthesisContexts.empty());
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return LSI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-03-01 14:11:25 +08:00
|
|
|
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
|
2012-01-06 11:05:34 +08:00
|
|
|
if (FunctionScopes.empty())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2013-01-20 09:04:14 +08:00
|
|
|
|
2016-11-11 20:36:20 +08:00
|
|
|
auto I = FunctionScopes.rbegin();
|
2017-03-01 14:11:25 +08:00
|
|
|
if (IgnoreNonLambdaCapturingScope) {
|
2016-11-11 20:36:20 +08:00
|
|
|
auto E = FunctionScopes.rend();
|
2017-03-01 14:11:25 +08:00
|
|
|
while (I != E && isa<CapturingScopeInfo>(*I) && !isa<LambdaScopeInfo>(*I))
|
2016-11-11 20:36:20 +08:00
|
|
|
++I;
|
|
|
|
if (I == E)
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
|
2014-04-27 02:29:13 +08:00
|
|
|
if (CurLSI && CurLSI->Lambda &&
|
|
|
|
!CurLSI->Lambda->Encloses(CurContext)) {
|
|
|
|
// We have switched contexts due to template instantiation.
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty());
|
2014-04-27 02:29:13 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CurLSI;
|
2012-01-06 11:05:34 +08:00
|
|
|
}
|
2019-08-27 06:51:28 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
// We have a generic lambda if we parsed auto parameters, or we have
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
// an associated template parameter list.
|
|
|
|
LambdaScopeInfo *Sema::getCurGenericLambda() {
|
|
|
|
if (LambdaScopeInfo *LSI = getCurLambda()) {
|
2019-05-04 18:49:46 +08:00
|
|
|
return (LSI->TemplateParams.size() ||
|
2014-05-26 14:22:03 +08:00
|
|
|
LSI->GLTemplateParameterList) ? LSI : nullptr;
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 11:05:34 +08:00
|
|
|
|
2012-06-20 08:34:58 +08:00
|
|
|
void Sema::ActOnComment(SourceRange Comment) {
|
2012-09-13 14:41:18 +08:00
|
|
|
if (!LangOpts.RetainCommentsFromSystemHeaders &&
|
|
|
|
SourceMgr.isInSystemHeader(Comment.getBegin()))
|
|
|
|
return;
|
[NFC] Move CommentOpts checks to the call sites that depend on it. (Re-applying r326501.)
When parsing comments, for example, for -Wdocumentation, slightly different
behaviour occurs when -fparse-all-comments is specified. However, these
differences are subtle:
1. All comments are saved during parsing, regardless of whether they are doc
comments or not.
2. "Maybe-doc" comments, like <, !, etc, are saved as such, instead of marking
them as ordinary comments. The maybe-doc type of comment is never saved
otherwise. (Warning on these is the impetus of -Wdocumentation.)
3. All comments are treated as doc comments in ASTContext, even if they are ordinary.
This change moves the logic for checking CommentOptions.ParseAllComments closer
to where it has an effect. The overall logic is unchanged, but checks of the
ParseAllComments flag are now done where the effect will be clearer.
Subscribers: cfe-commits
llvm-svn: 326512
2018-03-02 08:07:45 +08:00
|
|
|
RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
|
2012-06-23 00:02:55 +08:00
|
|
|
if (RC.isAlmostTrailingComment()) {
|
|
|
|
SourceRange MagicMarkerRange(Comment.getBegin(),
|
|
|
|
Comment.getBegin().getLocWithOffset(3));
|
|
|
|
StringRef MagicMarkerText;
|
|
|
|
switch (RC.getKind()) {
|
2012-07-04 15:30:26 +08:00
|
|
|
case RawComment::RCK_OrdinaryBCPL:
|
2012-06-23 00:02:55 +08:00
|
|
|
MagicMarkerText = "///<";
|
|
|
|
break;
|
2012-07-04 15:30:26 +08:00
|
|
|
case RawComment::RCK_OrdinaryC:
|
2012-06-23 00:02:55 +08:00
|
|
|
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);
|
|
|
|
}
|
2012-06-20 08:34:58 +08:00
|
|
|
Context.addComment(RC);
|
|
|
|
}
|
|
|
|
|
2010-06-01 17:23:16 +08:00
|
|
|
// Pin this vtable to this file.
|
2015-10-20 21:23:58 +08:00
|
|
|
ExternalSemaSource::~ExternalSemaSource() {}
|
2019-12-15 23:09:20 +08:00
|
|
|
char ExternalSemaSource::ID;
|
2010-08-27 07:41:50 +08:00
|
|
|
|
2012-01-25 08:49:42 +08:00
|
|
|
void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
|
2016-04-30 03:04:05 +08:00
|
|
|
void ExternalSemaSource::updateOutOfDateSelector(Selector Sel) { }
|
2010-09-29 04:23:00 +08:00
|
|
|
|
2011-06-29 00:20:02 +08:00
|
|
|
void ExternalSemaSource::ReadKnownNamespaces(
|
2013-01-20 09:04:14 +08:00
|
|
|
SmallVectorImpl<NamespaceDecl *> &Namespaces) {
|
2011-06-29 00:20:02 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 16:13:20 +08:00
|
|
|
void ExternalSemaSource::ReadUndefinedButUsed(
|
2016-03-26 05:49:43 +08:00
|
|
|
llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {}
|
2013-01-26 08:35:08 +08:00
|
|
|
|
2015-05-19 03:59:11 +08:00
|
|
|
void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
|
|
|
|
FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Figure out if an expression could be turned into a call.
|
2011-05-05 06:10:40 +08:00
|
|
|
///
|
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
/// \param E - The expression to examine.
|
|
|
|
/// \param ZeroArgCallReturnTy - If the expression can be turned into a call
|
|
|
|
/// with no arguments, this parameter is set to the type returned by such a
|
|
|
|
/// call; otherwise, it is set to an empty QualType.
|
2011-10-12 07:14:30 +08:00
|
|
|
/// \param OverloadSet - If the expression is an overloaded function
|
2011-05-05 06:10:40 +08:00
|
|
|
/// name, this parameter is populated with the decls of the various overloads.
|
2013-06-22 07:54:45 +08:00
|
|
|
bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
|
|
|
|
UnresolvedSetImpl &OverloadSet) {
|
2011-05-05 06:10:40 +08:00
|
|
|
ZeroArgCallReturnTy = QualType();
|
2011-10-12 07:14:30 +08:00
|
|
|
OverloadSet.clear();
|
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
const OverloadExpr *Overloads = nullptr;
|
2013-06-22 07:54:45 +08:00
|
|
|
bool IsMemExpr = false;
|
2011-10-12 07:14:30 +08:00
|
|
|
if (E.getType() == Context.OverloadTy) {
|
|
|
|
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
|
|
|
|
|
2013-06-04 08:28:46 +08:00
|
|
|
// Ignore overloads that are pointer-to-member constants.
|
|
|
|
if (FR.HasFormOfMemberPointer)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Overloads = FR.Expression;
|
|
|
|
} else if (E.getType() == Context.BoundMemberTy) {
|
|
|
|
Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens());
|
2013-06-22 07:54:45 +08:00
|
|
|
IsMemExpr = true;
|
2013-06-04 08:28:46 +08:00
|
|
|
}
|
2013-06-22 07:54:45 +08:00
|
|
|
|
|
|
|
bool Ambiguous = false;
|
2018-07-20 22:13:28 +08:00
|
|
|
bool IsMV = false;
|
2013-06-22 07:54:45 +08:00
|
|
|
|
2013-06-04 08:28:46 +08:00
|
|
|
if (Overloads) {
|
2011-05-05 06:10:40 +08:00
|
|
|
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
|
|
|
|
DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
|
2011-10-12 07:14:30 +08:00
|
|
|
OverloadSet.addDecl(*it);
|
|
|
|
|
2013-06-22 07:54:45 +08:00
|
|
|
// Check whether the function is a non-template, non-member which takes no
|
2011-10-12 07:14:30 +08:00
|
|
|
// arguments.
|
2013-06-22 07:54:45 +08:00
|
|
|
if (IsMemExpr)
|
|
|
|
continue;
|
2011-10-12 07:14:30 +08:00
|
|
|
if (const FunctionDecl *OverloadDecl
|
|
|
|
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
|
2013-06-04 08:28:46 +08:00
|
|
|
if (OverloadDecl->getMinRequiredArguments() == 0) {
|
2018-07-20 22:13:28 +08:00
|
|
|
if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
|
|
|
|
(!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
|
|
|
|
OverloadDecl->isCPUSpecificMultiVersion()))) {
|
2013-06-04 08:28:46 +08:00
|
|
|
ZeroArgCallReturnTy = QualType();
|
|
|
|
Ambiguous = true;
|
2018-07-20 22:13:28 +08:00
|
|
|
} else {
|
2014-01-26 00:55:45 +08:00
|
|
|
ZeroArgCallReturnTy = OverloadDecl->getReturnType();
|
2018-07-20 22:13:28 +08:00
|
|
|
IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
|
|
|
|
OverloadDecl->isCPUSpecificMultiVersion();
|
|
|
|
}
|
2013-06-04 08:28:46 +08:00
|
|
|
}
|
2011-05-05 06:10:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-10-12 07:14:30 +08:00
|
|
|
|
2013-06-22 07:54:45 +08:00
|
|
|
// If it's not a member, use better machinery to try to resolve the call
|
|
|
|
if (!IsMemExpr)
|
|
|
|
return !ZeroArgCallReturnTy.isNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt to call the member with no arguments - this will correctly handle
|
|
|
|
// member templates with defaults/deduction of template arguments, overloads
|
|
|
|
// with default arguments, etc.
|
2013-07-09 07:35:04 +08:00
|
|
|
if (IsMemExpr && !E.isTypeDependent()) {
|
2019-08-17 03:53:22 +08:00
|
|
|
Sema::TentativeAnalysisScope Trap(*this);
|
2014-05-26 14:22:03 +08:00
|
|
|
ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(),
|
|
|
|
None, SourceLocation());
|
2013-06-22 07:54:45 +08:00
|
|
|
if (R.isUsable()) {
|
|
|
|
ZeroArgCallReturnTy = R.get()->getType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2011-05-05 06:10:40 +08:00
|
|
|
}
|
|
|
|
|
2011-10-12 07:14:30 +08:00
|
|
|
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
|
2011-05-05 06:10:40 +08:00
|
|
|
if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
|
|
|
|
if (Fun->getMinRequiredArguments() == 0)
|
2014-01-26 00:55:45 +08:00
|
|
|
ZeroArgCallReturnTy = Fun->getReturnType();
|
2011-05-05 06:10:40 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have an expression that's convenient to get a FunctionDecl from,
|
|
|
|
// but we can at least check if the type is "function of 0 arguments".
|
|
|
|
QualType ExprTy = E.getType();
|
2014-05-26 14:22:03 +08:00
|
|
|
const FunctionType *FunTy = nullptr;
|
2011-05-05 08:59:35 +08:00
|
|
|
QualType PointeeTy = ExprTy->getPointeeType();
|
|
|
|
if (!PointeeTy.isNull())
|
|
|
|
FunTy = PointeeTy->getAs<FunctionType>();
|
2011-05-05 06:10:40 +08:00
|
|
|
if (!FunTy)
|
|
|
|
FunTy = ExprTy->getAs<FunctionType>();
|
|
|
|
|
|
|
|
if (const FunctionProtoType *FPT =
|
|
|
|
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
|
2014-01-21 04:26:09 +08:00
|
|
|
if (FPT->getNumParams() == 0)
|
2014-01-26 00:55:45 +08:00
|
|
|
ZeroArgCallReturnTy = FunTy->getReturnType();
|
2011-05-05 06:10:40 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Give notes for a set of overloads.
|
2011-05-05 06:10:40 +08:00
|
|
|
///
|
2013-06-22 07:54:45 +08:00
|
|
|
/// A companion to tryExprAsCall. In cases when the name that the programmer
|
2011-05-05 06:10:40 +08:00
|
|
|
/// wrote was an overloaded function, we may be able to make some guesses about
|
|
|
|
/// plausible overloads based on their return types; such guesses can be handed
|
|
|
|
/// off to this method to be emitted as notes.
|
|
|
|
///
|
|
|
|
/// \param Overloads - The overloads to note.
|
|
|
|
/// \param FinalNoteLoc - If we've suppressed printing some overloads due to
|
|
|
|
/// -fshow-overloads=best, this is the location to attach to the note about too
|
|
|
|
/// many candidates. Typically this will be the location of the original
|
|
|
|
/// ill-formed expression.
|
2011-10-12 07:14:30 +08:00
|
|
|
static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
|
|
|
|
const SourceLocation FinalNoteLoc) {
|
2021-02-26 10:14:40 +08:00
|
|
|
unsigned ShownOverloads = 0;
|
|
|
|
unsigned SuppressedOverloads = 0;
|
2011-05-05 06:10:40 +08:00
|
|
|
for (UnresolvedSetImpl::iterator It = Overloads.begin(),
|
|
|
|
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
|
2021-01-31 11:00:24 +08:00
|
|
|
if (ShownOverloads >= S.Diags.getNumOverloadCandidatesToShow()) {
|
2011-05-05 06:10:40 +08:00
|
|
|
++SuppressedOverloads;
|
|
|
|
continue;
|
|
|
|
}
|
2011-10-12 07:14:30 +08:00
|
|
|
|
|
|
|
NamedDecl *Fn = (*It)->getUnderlyingDecl();
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
// Don't print overloads for non-default multiversioned functions.
|
|
|
|
if (const auto *FD = Fn->getAsFunction()) {
|
2018-07-20 22:13:28 +08:00
|
|
|
if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() &&
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
!FD->getAttr<TargetAttr>()->isDefaultVersion())
|
|
|
|
continue;
|
|
|
|
}
|
2011-11-16 05:43:28 +08:00
|
|
|
S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
|
2011-05-05 06:10:40 +08:00
|
|
|
++ShownOverloads;
|
|
|
|
}
|
2011-10-12 07:14:30 +08:00
|
|
|
|
2021-01-31 11:00:24 +08:00
|
|
|
S.Diags.overloadCandidatesShown(ShownOverloads);
|
|
|
|
|
2011-05-05 06:10:40 +08:00
|
|
|
if (SuppressedOverloads)
|
2011-10-12 07:14:30 +08:00
|
|
|
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);
|
2014-01-26 00:55:45 +08:00
|
|
|
QualType OverloadResultTy = OverloadDecl->getReturnType();
|
2011-10-12 07:14:30 +08:00
|
|
|
if (IsPlausibleResult(OverloadResultTy))
|
|
|
|
PlausibleOverloads.addDecl(It.getDecl());
|
|
|
|
}
|
|
|
|
noteOverloads(S, PlausibleOverloads, Loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determine whether the given expression can be called by just
|
|
|
|
/// putting parentheses after it. Notably, expressions with unary
|
|
|
|
/// operators can't be because the unary operator will start parsing
|
|
|
|
/// outside the call.
|
|
|
|
static bool IsCallableWithAppend(Expr *E) {
|
|
|
|
E = E->IgnoreImplicit();
|
|
|
|
return (!isa<CStyleCastExpr>(E) &&
|
|
|
|
!isa<UnaryOperator>(E) &&
|
|
|
|
!isa<BinaryOperator>(E) &&
|
|
|
|
!isa<CXXOperatorCallExpr>(E));
|
|
|
|
}
|
|
|
|
|
2018-07-20 22:13:28 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-10-12 07:14:30 +08:00
|
|
|
bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
|
|
|
|
bool ForceComplain,
|
|
|
|
bool (*IsPlausibleResult)(QualType)) {
|
|
|
|
SourceLocation Loc = E.get()->getExprLoc();
|
|
|
|
SourceRange Range = E.get()->getSourceRange();
|
|
|
|
|
|
|
|
QualType ZeroArgCallTy;
|
|
|
|
UnresolvedSet<4> Overloads;
|
2013-06-22 07:54:45 +08:00
|
|
|
if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
|
2011-10-12 07:14:30 +08:00
|
|
|
!ZeroArgCallTy.isNull() &&
|
|
|
|
(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
|
|
|
|
// At this point, we know E is potentially callable with 0
|
|
|
|
// arguments and that it returns something of a reasonable type,
|
|
|
|
// so we can emit a fixit and carry on pretending that E was
|
|
|
|
// actually a CallExpr.
|
2015-11-15 10:31:46 +08:00
|
|
|
SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
|
2018-07-20 22:13:28 +08:00
|
|
|
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);
|
2011-10-12 07:14:30 +08:00
|
|
|
|
|
|
|
// FIXME: Try this before emitting the fixit, and suppress diagnostics
|
|
|
|
// while doing so.
|
2019-05-08 09:36:36 +08:00
|
|
|
E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
|
2013-08-22 03:09:44 +08:00
|
|
|
Range.getEnd().getLocWithOffset(1));
|
2011-10-12 07:14:30 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ForceComplain) return false;
|
|
|
|
|
2018-07-20 22:13:28 +08:00
|
|
|
bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
|
|
|
|
Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range;
|
|
|
|
if (!IsMV)
|
|
|
|
notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
|
2011-10-12 07:14:30 +08:00
|
|
|
E = ExprError();
|
|
|
|
return true;
|
2011-05-05 06:10:40 +08:00
|
|
|
}
|
2013-03-15 06:56:43 +08:00
|
|
|
|
|
|
|
IdentifierInfo *Sema::getSuperIdentifier() const {
|
|
|
|
if (!Ident_super)
|
|
|
|
Ident_super = &Context.Idents.get("super");
|
|
|
|
return Ident_super;
|
|
|
|
}
|
2013-04-17 03:37:38 +08:00
|
|
|
|
2013-06-21 05:44:55 +08:00
|
|
|
IdentifierInfo *Sema::getFloat128Identifier() const {
|
|
|
|
if (!Ident___float128)
|
|
|
|
Ident___float128 = &Context.Idents.get("__float128");
|
|
|
|
return Ident___float128;
|
|
|
|
}
|
|
|
|
|
2013-04-17 03:37:38 +08:00
|
|
|
void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
|
2019-08-22 11:34:30 +08:00
|
|
|
CapturedRegionKind K,
|
|
|
|
unsigned OpenMPCaptureLevel) {
|
|
|
|
auto *CSI = new CapturedRegionScopeInfo(
|
2016-05-17 16:55:33 +08:00
|
|
|
getDiagnostics(), S, CD, RD, CD->getContextParam(), K,
|
2019-08-22 11:34:30 +08:00
|
|
|
(getLangOpts().OpenMP && K == CR_OpenMP) ? getOpenMPNestingLevel() : 0,
|
|
|
|
OpenMPCaptureLevel);
|
2013-04-17 03:37:38 +08:00
|
|
|
CSI->ReturnType = Context.VoidTy;
|
|
|
|
FunctionScopes.push_back(CSI);
|
|
|
|
}
|
|
|
|
|
|
|
|
CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
|
|
|
|
if (FunctionScopes.empty())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2013-04-17 03:37:38 +08:00
|
|
|
|
|
|
|
return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
|
|
|
|
}
|
2015-05-19 03:59:11 +08:00
|
|
|
|
|
|
|
const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
|
|
|
|
Sema::getMismatchingDeleteExpressions() const {
|
|
|
|
return DeleteExprs;
|
|
|
|
}
|
2016-12-18 13:18:55 +08:00
|
|
|
|
|
|
|
void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
|
|
|
|
if (ExtStr.empty())
|
|
|
|
return;
|
|
|
|
llvm::SmallVector<StringRef, 1> Exts;
|
|
|
|
ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
|
|
|
|
auto CanT = T.getCanonicalType().getTypePtr();
|
|
|
|
for (auto &I : Exts)
|
|
|
|
OpenCLTypeExtMap[CanT].insert(I.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
|
|
|
|
llvm::SmallVector<StringRef, 1> Exts;
|
|
|
|
ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
|
|
|
|
if (Exts.empty())
|
|
|
|
return;
|
|
|
|
for (auto &I : Exts)
|
|
|
|
OpenCLDeclExtMap[FD].insert(I.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::setCurrentOpenCLExtensionForType(QualType T) {
|
|
|
|
if (CurrOpenCLExtension.empty())
|
|
|
|
return;
|
|
|
|
setOpenCLExtensionForType(T, CurrOpenCLExtension);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
|
|
|
|
if (CurrOpenCLExtension.empty())
|
|
|
|
return;
|
|
|
|
setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
|
|
|
|
}
|
|
|
|
|
2018-10-11 21:35:34 +08:00
|
|
|
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) {
|
|
|
|
auto Loc = Map.find(FDT);
|
2020-04-11 23:18:54 +08:00
|
|
|
return llvm::join(Loc->second, " ");
|
2018-10-11 21:35:34 +08:00
|
|
|
}
|
|
|
|
|
2016-12-18 13:18:55 +08:00
|
|
|
bool Sema::isOpenCLDisabledDecl(Decl *FD) {
|
|
|
|
auto Loc = OpenCLDeclExtMap.find(FD);
|
|
|
|
if (Loc == OpenCLDeclExtMap.end())
|
|
|
|
return false;
|
|
|
|
for (auto &I : Loc->second) {
|
2021-03-05 21:23:49 +08:00
|
|
|
if (!getOpenCLOptions().isAvailableOption(I, getLangOpts()))
|
2016-12-18 13:18:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
|
|
|
|
bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
|
|
|
|
DiagInfoT DiagInfo, MapT &Map,
|
|
|
|
unsigned Selector,
|
|
|
|
SourceRange SrcRange) {
|
|
|
|
auto Loc = Map.find(D);
|
|
|
|
if (Loc == Map.end())
|
|
|
|
return false;
|
|
|
|
bool Disabled = false;
|
|
|
|
for (auto &I : Loc->second) {
|
2021-03-05 21:23:49 +08:00
|
|
|
if (I != CurrOpenCLExtension &&
|
|
|
|
!getOpenCLOptions().isAvailableOption(I, getLangOpts())) {
|
2016-12-18 13:18:55 +08:00
|
|
|
Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
|
|
|
|
<< I << SrcRange;
|
|
|
|
Disabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Disabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
|
|
|
|
// Check extensions for declared types.
|
|
|
|
Decl *Decl = nullptr;
|
|
|
|
if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
|
|
|
|
Decl = TypedefT->getDecl();
|
|
|
|
if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
|
|
|
|
Decl = TagT->getDecl();
|
|
|
|
auto Loc = DS.getTypeSpecTypeLoc();
|
2018-09-03 19:43:22 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2016-12-18 13:18:55 +08:00
|
|
|
if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Check extensions for builtin types.
|
|
|
|
return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
|
|
|
|
QT, OpenCLTypeExtMap);
|
|
|
|
}
|
|
|
|
|
2017-06-30 22:23:01 +08:00
|
|
|
bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) {
|
|
|
|
IdentifierInfo *FnName = D.getIdentifier();
|
2018-08-10 05:08:08 +08:00
|
|
|
return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName,
|
2016-12-18 13:18:55 +08:00
|
|
|
OpenCLDeclExtMap, 1, D.getSourceRange());
|
|
|
|
}
|