Thanks for the comments! I've also rebased this to trunk.
Hi jdennett,
http://llvm-reviews.chandlerc.com/D1213
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1213?vs=2989&id=3081#toc
Files:
include/clang/Sema/ExternalSemaSource.h
include/clang/Sema/MultiplexExternalSemaSource.h
lib/Sema/MultiplexExternalSemaSource.cpp
lib/Sema/SemaType.cpp
unittests/CMakeLists.txt
unittests/Makefile
unittests/Sema/CMakeLists.txt
unittests/Sema/ExternalSemaSourceTest.cpp
unittests/Sema/Makefile
Index: include/clang/Sema/ExternalSemaSource.h
===================================================================
--- include/clang/Sema/ExternalSemaSource.h
+++ include/clang/Sema/ExternalSemaSource.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/MapVector.h"
#include <utility>
@@ -177,6 +178,19 @@
SmallVectorImpl<std::pair<ValueDecl *,
SourceLocation> > &Pending) {}
+
+ /// \brief Produces a diagnostic note if the external source contains a
+ /// complete definition for \p T.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T)
+ { return false; }
+
// isa/cast/dyn_cast support
static bool classof(const ExternalASTSource *Source) {
return Source->SemaSource;
Index: include/clang/Sema/MultiplexExternalSemaSource.h
===================================================================
--- include/clang/Sema/MultiplexExternalSemaSource.h
+++ include/clang/Sema/MultiplexExternalSemaSource.h
@@ -322,6 +322,18 @@
virtual void ReadPendingInstantiations(
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending);
+ /// \brief Produces a diagnostic note if one of the attached sources
+ /// contains a complete definition for \p T. Queries the sources in list
+ /// order until the first one claims that a diagnostic was produced.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T);
+
// isa/cast/dyn_cast support
static bool classof(const MultiplexExternalSemaSource*) { return true; }
//static bool classof(const ExternalSemaSource*) { return true; }
Index: lib/Sema/MultiplexExternalSemaSource.cpp
===================================================================
--- lib/Sema/MultiplexExternalSemaSource.cpp
+++ lib/Sema/MultiplexExternalSemaSource.cpp
@@ -267,3 +267,12 @@
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadPendingInstantiations(Pending);
}
+
+bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType(
+ SourceLocation Loc, QualType T) {
+ for (size_t I = 0, E = Sources.size(); I < E; ++I) {
+ if (Sources[I]->MaybeDiagnoseMissingCompleteType(Loc, T))
+ return true;
+ }
+ return false;
+}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5025,6 +5025,11 @@
if (IFace && !IFace->getDecl()->isInvalidDecl())
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
+ // If we have external information that we can use to suggest a fix,
+ // produce a note.
+ if (ExternalSource)
+ ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
+
return true;
}
Index: unittests/CMakeLists.txt
===================================================================
--- unittests/CMakeLists.txt
+++ unittests/CMakeLists.txt
@@ -19,4 +19,5 @@
add_subdirectory(AST)
add_subdirectory(Tooling)
add_subdirectory(Format)
+ add_subdirectory(Sema)
endif()
Index: unittests/Makefile
===================================================================
--- unittests/Makefile
+++ unittests/Makefile
@@ -23,7 +23,7 @@
endif
ifeq ($(ENABLE_CLANG_REWRITER),1)
-PARALLEL_DIRS += ASTMatchers AST Tooling
+PARALLEL_DIRS += ASTMatchers AST Tooling Sema
endif
ifeq ($(ENABLE_CLANG_STATIC_ANALYZER),1)
Index: unittests/Sema/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/Sema/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_clang_unittest(SemaTests
+ ExternalSemaSourceTest.cpp
+ )
+
+target_link_libraries(SemaTests
+ clangAST clangASTMatchers clangTooling
+ )
Index: unittests/Sema/ExternalSemaSourceTest.cpp
===================================================================
--- /dev/null
+++ unittests/Sema/ExternalSemaSourceTest.cpp
@@ -0,0 +1,100 @@
+//=== unittests/Sema/ExternalSemaSourceTest.cpp - ExternalSemaSource tests ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::tooling;
+
+namespace {
+
+class CompleteTypeDiagnoser : public clang::ExternalSemaSource {
+public:
+ CompleteTypeDiagnoser(bool MockResult) : CallCount(0), Result(MockResult) {}
+
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation L, QualType T) {
+ ++CallCount;
+ return Result;
+ }
+
+ int CallCount;
+ bool Result;
+};
+
+class ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
+protected:
+ virtual clang::ASTConsumer *
+ CreateASTConsumer(clang::CompilerInstance &Compiler,
+ llvm::StringRef /* dummy */) {
+ return new clang::ASTConsumer();
+ }
+
+ virtual void ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ ASSERT_FALSE(CI.hasSema());
+ CI.createSema(getTranslationUnitKind(), NULL);
+ for (size_t I = 0, E = Sources.size(); I < E; ++I)
+ CI.getSema().addExternalSource(Sources[I]);
+ ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
+ CI.getFrontendOpts().SkipFunctionBodies);
+ }
+
+public:
+ void PushSource(clang::ExternalSemaSource *Source) {
+ Sources.push_back(Source);
+ }
+
+private:
+ std::vector<clang::ExternalSemaSource *> Sources;
+};
+
+// We should only try MaybeDiagnoseMissingCompleteType if we can't otherwise
+// solve the problem.
+TEST(ExternalSemaSource, TryOtherTacticsBeforeDiagnosing) {
+ llvm::OwningPtr<ExternalSemaSourceInstaller> Installer(
+ new ExternalSemaSourceInstaller);
+ CompleteTypeDiagnoser Diagnoser(false);
+ Installer->PushSource(&Diagnoser);
+ std::vector<std::string> Args(1, "-std=c++11");
+ // This code hits the class template specialization/class member of a class
+ // template specialization checks in Sema::RequireCompleteTypeImpl.
+ ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
+ Installer.take(),
+ "template <typename T> struct S { class C { }; }; S<char>::C SCInst;",
+ Args));
+ ASSERT_EQ(0, Diagnoser.CallCount);
+}
+
+// The first ExternalSemaSource where MaybeDiagnoseMissingCompleteType returns
+// true should be the last one called.
+TEST(ExternalSemaSource, FirstDiagnoserTaken) {
+ llvm::OwningPtr<ExternalSemaSourceInstaller> Installer(
+ new ExternalSemaSourceInstaller);
+ CompleteTypeDiagnoser First(false);
+ CompleteTypeDiagnoser Second(true);
+ CompleteTypeDiagnoser Third(true);
+ Installer->PushSource(&First);
+ Installer->PushSource(&Second);
+ Installer->PushSource(&Third);
+ std::vector<std::string> Args(1, "-std=c++11");
+ ASSERT_FALSE(clang::tooling::runToolOnCodeWithArgs(
+ Installer.take(), "class Incomplete; Incomplete IncompleteInstance;",
+ Args));
+ ASSERT_EQ(1, First.CallCount);
+ ASSERT_EQ(1, Second.CallCount);
+ ASSERT_EQ(0, Third.CallCount);
+}
+
+} // anonymous namespace
Index: unittests/Sema/Makefile
===================================================================
--- /dev/null
+++ unittests/Sema/Makefile
@@ -0,0 +1,19 @@
+##===- unittests/Sema/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL = ../..
+TESTNAME = Sema
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewriteCore.a clangRewriteFrontend.a \
+ clangParse.a clangSema.a clangAnalysis.a \
+ clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits