aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-07-01 10:37:29 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-07-01 10:37:29 +0000
commit07952324dda0e758c17f8bc3015793c65c51c48c (patch)
treedf23760bd379514f0adb730fe44cb2642df6d58c /lib/Sema/SemaDecl.cpp
parentaae2d7418b7004fde1ba08fe60db219d0c95ff30 (diff)
Add Sema support for C++ classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52956 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp110
1 files changed, 83 insertions, 27 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6b528b6bed..3b0e2e6f38 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -44,19 +44,38 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) {
return 0;
}
+DeclContext *Sema::getDCParent(DeclContext *DC) {
+ // If CurContext is a ObjC method, getParent() will return NULL.
+ if (isa<ObjCMethodDecl>(DC))
+ return Context.getTranslationUnitDecl();
+
+ // A C++ inline method is parsed *after* the topmost class it was declared in
+ // is fully parsed (it's "complete").
+ // The parsing of a C++ inline method happens at the declaration context of
+ // the topmost (non-nested) class it is declared in.
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
+ assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record.");
+ DC = MD->getParent();
+ while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getParent()))
+ DC = RD;
+
+ // Return the declaration context of the topmost class the inline method is
+ // declared in.
+ return DC;
+ }
+
+ return DC->getParent();
+}
+
void Sema::PushDeclContext(DeclContext *DC) {
- assert( ( (isa<ObjCMethodDecl>(DC) && isa<TranslationUnitDecl>(CurContext))
- || DC->getParent() == CurContext ) &&
- "The next DeclContext should be directly contained in the current one.");
+ assert(getDCParent(DC) == CurContext &&
+ "The next DeclContext should be directly contained in the current one.");
CurContext = DC;
}
void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
- // If CurContext is a ObjC method, getParent() will return NULL.
- CurContext = isa<ObjCMethodDecl>(CurContext)
- ? Context.getTranslationUnitDecl()
- : CurContext->getParent();
+ CurContext = getDCParent(CurContext);
}
/// Add this decl to the scope shadowed decl chains.
@@ -646,10 +665,19 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
}
bool isInline = D.getDeclSpec().isInlineSpecified();
- FunctionDecl *NewFD = FunctionDecl::Create(Context, CurContext,
- D.getIdentifierLoc(),
- II, R, SC, isInline,
- LastDeclarator);
+ FunctionDecl *NewFD;
+ if (D.getContext() == Declarator::MemberContext) {
+ // This is a C++ method declaration.
+ NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
+ D.getIdentifierLoc(), II, R,
+ (SC == FunctionDecl::Static), isInline,
+ LastDeclarator);
+ } else {
+ NewFD = FunctionDecl::Create(Context, CurContext,
+ D.getIdentifierLoc(),
+ II, R, SC, isInline,
+ LastDeclarator);
+ }
// Handle attributes.
ProcessDeclAttributes(NewFD, D);
@@ -728,19 +756,27 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
}
- if (S->getFnParent() == 0) {
- // C99 6.9p2: The storage-class specifiers auto and register shall not
- // appear in the declaration specifiers in an external declaration.
- if (SC == VarDecl::Auto || SC == VarDecl::Register) {
- Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
- R.getAsString());
- InvalidDecl = true;
- }
- NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
- II, R, SC, LastDeclarator);
+ if (D.getContext() == Declarator::MemberContext) {
+ assert(SC == VarDecl::Static && "Invalid storage class for member!");
+ // This is a static data member for a C++ class.
+ NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
+ D.getIdentifierLoc(), II,
+ R, LastDeclarator);
} else {
- NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
- II, R, SC, LastDeclarator);
+ if (S->getFnParent() == 0) {
+ // C99 6.9p2: The storage-class specifiers auto and register shall not
+ // appear in the declaration specifiers in an external declaration.
+ if (SC == VarDecl::Auto || SC == VarDecl::Register) {
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
+ R.getAsString());
+ InvalidDecl = true;
+ }
+ NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
+ II, R, SC, LastDeclarator);
+ } else {
+ NewVD = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
+ II, R, SC, LastDeclarator);
+ }
}
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(NewVD, D);
@@ -1506,7 +1542,13 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
}
}
}
- Decl *decl = static_cast<Decl*>(ActOnDeclarator(GlobalScope, D, 0));
+
+ return ActOnStartOfFunctionDef(FnBodyScope,
+ ActOnDeclarator(GlobalScope, D, 0));
+}
+
+Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
+ Decl *decl = static_cast<Decl*>(D);
FunctionDecl *FD = cast<FunctionDecl>(decl);
PushDeclContext(FD);
@@ -1707,8 +1749,12 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// struct X { int A; } D; D should chain to X.
- New = RecordDecl::Create(Context, Kind, CurContext, Loc, Name, 0);
- }
+ if (getLangOptions().CPlusPlus)
+ // FIXME: Look for a way to use RecordDecl for simple structs.
+ New = CXXRecordDecl::Create(Context, Kind, CurContext, Loc, Name, 0);
+ else
+ New = RecordDecl::Create(Context, Kind, CurContext, Loc, Name, 0);
+ }
// If this has an identifier, add it to the scope stack.
if (Name) {
@@ -1843,7 +1889,17 @@ Sema::DeclTy *Sema::ActOnField(Scope *S,
}
}
// FIXME: Chain fielddecls together.
- FieldDecl *NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
+ FieldDecl *NewFD;
+
+ if (getLangOptions().CPlusPlus) {
+ // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
+ NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
+ Loc, II, T, BitWidth);
+ if (II)
+ PushOnScopeChains(NewFD, S);
+ }
+ else
+ NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
ProcessDeclAttributes(NewFD, D);