mirror of https://github.com/microsoft/clang.git
[Frontend] Handle skipped bodies in template instantiations
Summary: - Fixed an assert in Sema::InstantiateFunctionDefinition and added support for instantiating a function template with skipped body. - Properly call setHasSkippedBody for FunctionTemplateDecl passed to Sema::ActOnSkippedFunctionBody. Reviewers: sepavloff, bkramer Reviewed By: sepavloff Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D41237 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321174 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0604b824fd
commit
08191e917b
|
@ -12179,9 +12179,11 @@ bool Sema::canSkipFunctionBody(Decl *D) {
|
|||
}
|
||||
|
||||
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
|
||||
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl))
|
||||
if (!Decl)
|
||||
return nullptr;
|
||||
if (FunctionDecl *FD = Decl->getAsFunction())
|
||||
FD->setHasSkippedBody();
|
||||
else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
|
||||
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Decl))
|
||||
MD->setHasSkippedBody();
|
||||
return Decl;
|
||||
}
|
||||
|
|
|
@ -3855,7 +3855,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
}
|
||||
|
||||
// Note, we should never try to instantiate a deleted function template.
|
||||
assert((Pattern || PatternDecl->isDefaulted()) &&
|
||||
assert((Pattern || PatternDecl->isDefaulted() ||
|
||||
PatternDecl->hasSkippedBody()) &&
|
||||
"unexpected kind of function template definition");
|
||||
|
||||
// C++1y [temp.explicit]p10:
|
||||
|
@ -3940,16 +3941,20 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
}
|
||||
}
|
||||
|
||||
// Instantiate the function body.
|
||||
StmtResult Body = SubstStmt(Pattern, TemplateArgs);
|
||||
if (PatternDecl->hasSkippedBody()) {
|
||||
ActOnSkippedFunctionBody(Function);
|
||||
} else {
|
||||
// Instantiate the function body.
|
||||
StmtResult Body = SubstStmt(Pattern, TemplateArgs);
|
||||
|
||||
if (Body.isInvalid())
|
||||
Function->setInvalidDecl();
|
||||
if (Body.isInvalid())
|
||||
Function->setInvalidDecl();
|
||||
|
||||
// FIXME: finishing the function body while in an expression evaluation
|
||||
// context seems wrong. Investigate more.
|
||||
ActOnFinishFunctionBody(Function, Body.get(),
|
||||
/*IsInstantiation=*/true);
|
||||
// FIXME: finishing the function body while in an expression evaluation
|
||||
// context seems wrong. Investigate more.
|
||||
ActOnFinishFunctionBody(Function, Body.get(),
|
||||
/*IsInstantiation=*/true);
|
||||
}
|
||||
|
||||
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s 2>&1 \
|
||||
// RUN: | FileCheck %s
|
||||
|
||||
|
||||
template <class T>
|
||||
struct Foo {
|
||||
inline int with_body() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
inline int without_body();
|
||||
};
|
||||
|
||||
|
||||
int bar = Foo<int>().with_body() + Foo<int>().without_body();
|
||||
// CHECK-NOT: warning: inline function 'Foo<int>::with_body' is not defined
|
||||
// CHECK: warning: inline function 'Foo<int>::without_body' is not defined
|
||||
|
||||
template <class T>
|
||||
inline int with_body() { return 10; }
|
||||
|
||||
template <class T>
|
||||
inline int without_body();
|
||||
|
||||
int baz = with_body<int>() + without_body<int>();
|
||||
// CHECK-NOT: warning: inline function 'with_body<int>' is not defined
|
||||
// CHECK: warning: inline function 'without_body<int>' is not defined
|
Loading…
Reference in New Issue