diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-04-13 21:30:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-04-13 21:30:24 +0000 |
commit | e37ac4ff1620ed2d7026f52baccbfa022d79ced1 (patch) | |
tree | acc5704dc77d184e356feceeabd435c91f584a5d /lib/Sema/SemaDeclCXX.cpp | |
parent | 2ce52f3fb95bf544db6bd3d91a72bce7d9cceb6c (diff) |
This patch adds very basic support for parsing and type-checking class
inheritance in C++. It'll parse the base-specifier list, e.g.,
class D : public B1, virtual public B2 { };
and do some of the simpler semantic checks (B1 and B2 are classes;
they aren't unions or incomplete types, etc).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49623 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 89440c0cf4..7202d2f2f1 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "clang/Basic/LangOptions.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" @@ -234,3 +235,51 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { } } } + +/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is +/// one entry in the base class list of a class specifier, for +/// 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, + DeclTy *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; + } + + // 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; + } + + // C++ [class.union]p1: + // A union shall not have base classes. + if (Decl->getKind() == Decl::Union) { + Diag(Decl->getLocation(), diag::err_base_clause_on_union, + SpecifierRange); + Decl->setInvalidDecl(); + return; + } + + // C++ [class.derived]p2: + // The class-name in a base-specifier shall not be an incompletely + // defined class. + if (BaseType->isIncompleteType()) { + Diag(BaseLoc, diag::err_incomplete_base_class, SpecifierRange); + return; + } + + // FIXME: C++ [class.mi]p3: + // A class shall not be specified as a direct base class of a + // derived class more than once. + + // FIXME: Attach base class to the record. +} |