explicit template specializations (which represent actual functions somebody wrote).
Along the way, refactor some other code which similarly cares about whether or
not they are looking at a template instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145547
91177308-0d34-0410-b5e6-
96231b3b80d8
/// be implicitly instantiated.
bool isImplicitlyInstantiable() const;
+ /// \brief Determines if the given function was instantiated from a
+ /// function template.
+ bool isTemplateInstantiation() const;
+
/// \brief Retrieve the function declaration from which this function could
/// be instantiated, if it is an instantiation (rather than a non-template
/// or a specialization, for example).
return true;
return PatternDecl->isInlined();
-}
+}
+
+bool FunctionDecl::isTemplateInstantiation() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return false;
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+ }
+ llvm_unreachable("All TSK values handled.");
+}
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
// Handle class scope explicit specialization special case.
// Don't suggest that template instantiations be marked "noreturn"
bool isTemplateInstantiation = false;
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) {
- switch (Function->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- break;
-
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- isTemplateInstantiation = true;
- break;
- }
- }
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
+ isTemplateInstantiation = Function->isTemplateInstantiation();
if (!isVirtualMethod && !isTemplateInstantiation)
D.diag_NeverFallThroughOrReturn =
// Different template instantiations can effectively change the control-flow
// and it is very difficult to prove that a snippet of code in a template
// is unreachable for all instantiations.
- if (S.ActiveTemplateInstantiations.empty())
+ bool isTemplateInstantiation = false;
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+ isTemplateInstantiation = Function->isTemplateInstantiation();
+ if (!isTemplateInstantiation)
CheckUnreachable(S, AC);
}
BugReporter &B,
ExprEngine &Eng) const {
CFGBlocksSet reachable, visited;
-
+
if (Eng.hasWorkRemaining())
return;
+ const Decl *D = 0;
CFG *C = 0;
ParentMap *PM = 0;
const LocationContext *LC = 0;
const ProgramPoint &P = I->getLocation();
LC = P.getLocationContext();
+ if (!D)
+ D = LC->getAnalysisDeclContext()->getDecl();
// Save the CFG if we don't have it already
if (!C)
C = LC->getAnalysisDeclContext()->getUnoptimizedCFG();
}
// Bail out if we didn't get the CFG or the ParentMap.
- if (!C || !PM)
+ if (!D || !C || !PM)
return;
+
+ // Don't do anything for template instantiations. Proving that code
+ // in a template instantiation is unreachable means proving that it is
+ // unreachable in all instantiations.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isTemplateInstantiation())
+ return;
// Find CFGBlocks that were not covered by any node
for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
test_unreachable_templates<TestUnreachableB>();
}
+// Do warn about explict template specializations, as they represent
+// actual concrete functions that somebody wrote.
+
+template <typename T> void funcToSpecialize() {}
+template <> void funcToSpecialize<int>() {
+ halt();
+ dead(); // expected-warning {{will never be executed}}
+}
+