diff options
| author | Ilya Biryukov <ibiryukov@google.com> | 2017-12-20 14:32:38 +0000 |
|---|---|---|
| committer | Ilya Biryukov <ibiryukov@google.com> | 2017-12-20 14:32:38 +0000 |
| commit | a27eca283b6e92b8520a84b2c1ce982766dfce7a (patch) | |
| tree | 0cfef0c1d3e04fc2a671e6439897945fbc67bba6 | |
| parent | 0d5016837dd4779b879562c1835f75d8f8e7a0af (diff) | |
| download | bcm5719-llvm-a27eca283b6e92b8520a84b2c1ce982766dfce7a.tar.gz bcm5719-llvm-a27eca283b6e92b8520a84b2c1ce982766dfce7a.zip | |
[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
llvm-svn: 321174
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 23 | ||||
| -rw-r--r-- | clang/test/Index/skipped-bodies-templates.cpp | 27 |
3 files changed, 45 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c60cc52f415..a1fc725f8df 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3febf5debee..b926e573ade 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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); diff --git a/clang/test/Index/skipped-bodies-templates.cpp b/clang/test/Index/skipped-bodies-templates.cpp new file mode 100644 index 00000000000..d8fbc28ebc2 --- /dev/null +++ b/clang/test/Index/skipped-bodies-templates.cpp @@ -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 |

