aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h10
-rw-r--r--lib/Sema/SemaDeclCXX.cpp75
-rw-r--r--lib/Sema/SemaOverload.cpp4
3 files changed, 72 insertions, 17 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index b176bc9ceb..48b32e8ce1 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -753,10 +753,14 @@ public:
// C++ Classes
//
/// ActOnBaseSpecifier - Parsed a base specifier
- virtual void ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeTy *basetype, SourceLocation BaseLoc);
+ virtual BaseResult ActOnBaseSpecifier(DeclTy *classdecl,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeTy *basetype, SourceLocation BaseLoc);
+ virtual void ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,
+ unsigned NumBases);
+
virtual void ActOnStartCXXClassDef(Scope *S, DeclTy *TagDecl,
SourceLocation LBrace);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fef205cb11..7c4444fab6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -20,6 +20,8 @@
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::equal
+#include <functional>
+#include <map>
using namespace clang;
@@ -260,23 +262,24 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
/// example:
/// class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
-void Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeTy *basetype, SourceLocation BaseLoc) {
+Sema::BaseResult
+Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeTy *basetype, SourceLocation BaseLoc) {
RecordDecl *Decl = (RecordDecl*)classdecl;
QualType BaseType = Context.getTypeDeclType((TypeDecl*)basetype);
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
Diag(BaseLoc, diag::err_base_must_be_class, SpecifierRange);
- return;
+ return true;
}
// C++ [class.union]p1:
// A union shall not be used as a base class.
if (BaseType->isUnionType()) {
Diag(BaseLoc, diag::err_union_as_base_class, SpecifierRange);
- return;
+ return true;
}
// C++ [class.union]p1:
@@ -284,8 +287,7 @@ void Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
if (Decl->isUnion()) {
Diag(Decl->getLocation(), diag::err_base_clause_on_union,
SpecifierRange);
- Decl->setInvalidDecl();
- return;
+ return true;
}
// C++ [class.derived]p2:
@@ -293,14 +295,63 @@ void Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
// defined class.
if (BaseType->isIncompleteType()) {
Diag(BaseLoc, diag::err_incomplete_base_class, SpecifierRange);
- return;
+ return true;
+ }
+
+ // Create the base specifier.
+ CXXBaseSpecifier *BS = CXXBaseSpecifier::Create(Context, SpecifierRange,
+ Virtual,
+ BaseType->isClassType(),
+ Access, BaseType);
+ return BS;
+}
+
+/// QualTypeOrder - Function object that provides a total ordering on
+/// QualType values.
+struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
+ bool operator()(QualType T1, QualType T2) {
+ return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
}
+};
+
+/// ActOnBaseSpecifiers - Attach the given base specifiers to the
+/// class, after checking whether there are any duplicate base
+/// classes.
+void Sema::ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,
+ unsigned NumBases) {
+ if (NumBases == 0)
+ return;
- // FIXME: C++ [class.mi]p3:
- // A class shall not be specified as a direct base class of a
- // derived class more than once.
+ // Used to keep track of which base types we have already seen, so
+ // that we can properly diagnose redundant direct base types. Note
+ // that the key is always the canonical type.
+ std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
+
+ // Copy non-redundant base specifiers into permanent storage.
+ CXXBaseSpecifier **InBaseSpecs = (CXXBaseSpecifier **)Bases;
+ CXXBaseSpecifier **StoredBaseSpecs = new CXXBaseSpecifier* [NumBases];
+ unsigned outIdx = 0;
+ for (unsigned inIdx = 0; inIdx < NumBases; ++inIdx) {
+ QualType NewBaseType
+ = Context.getCanonicalType(InBaseSpecs[inIdx]->getType());
+ if (KnownBaseTypes[NewBaseType]) {
+ // C++ [class.mi]p3:
+ // A class shall not be specified as a direct base class of a
+ // derived class more than once.
+ Diag(InBaseSpecs[inIdx]->getSourceRange().getBegin(),
+ diag::err_duplicate_base_class,
+ KnownBaseTypes[NewBaseType]->getType().getAsString(),
+ InBaseSpecs[inIdx]->getSourceRange());
+ } else {
+ // Okay, add this new base class.
+ KnownBaseTypes[NewBaseType] = InBaseSpecs[inIdx];
+ StoredBaseSpecs[outIdx++] = InBaseSpecs[inIdx];
+ }
+ }
- // FIXME: Attach base class to the record.
+ // Attach the remaining base class specifiers to the derived class.
+ CXXRecordDecl *Decl = (CXXRecordDecl*)ClassDecl;
+ Decl->setBases(StoredBaseSpecs, outIdx);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index cafdf8794a..19bc13a146 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -664,7 +664,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType)
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
- // pointers (FIXME: or pointers-to-members) and do it all again
+ // pointers or pointers-to-members and do it all again
// until there are no more pointers or pointers-to-members left to
// unwrap.
UnwrappedAnyPointer = true;
@@ -839,7 +839,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
- // pointers (FIXME: or pointers-to-members) and do it all again
+ // pointers or pointers-to-members and do it all again
// until there are no more pointers or pointers-to-members left
// to unwrap. This essentially mimics what
// IsQualificationConversion does, but here we're checking for a