aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-01-24 21:53:27 +0000
committerChris Lattner <sabre@nondot.org>2009-01-24 21:53:27 +0000
commitaf707ab8fbb9451e8febb8d766f6c043628125c4 (patch)
treefabcc17e795c47c3e68c1dc2e5d34b1b610be7a9
parentb9037594f5e02f66c4fa697d9dec2359faba1bc3 (diff)
add initial support for the gcc "alignof(decl) is the alignment of the decl
not the type" semantics. This can definitely be improved, but is better than what we had. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62939 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--lib/AST/ASTContext.cpp20
-rw-r--r--lib/AST/ExprConstant.cpp19
3 files changed, 39 insertions, 5 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 9ac6027570..927d65b99f 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -403,6 +403,11 @@ public:
return getTypeInfo(T).second;
}
+ /// getDeclAlign - Return a conservative estimate of the alignment of the
+ /// specified decl. Note that bitfields do not have a valid alignment, so
+ /// this method will assert on them.
+ unsigned getDeclAlign(const Decl *D);
+
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f3243c25ae..63e4ccc241 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -260,6 +260,26 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
}
}
+/// getDeclAlign - Return a conservative estimate of the alignment of the
+/// specified decl. Note that bitfields do not have a valid alignment, so
+/// this method will assert on them.
+unsigned ASTContext::getDeclAlign(const Decl *D) {
+ // FIXME: If attribute(align) is specified on the decl, round up to it.
+
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ QualType T = VD->getType();
+ // Incomplete or function types default to 1.
+ if (T->isIncompleteType() || T->isFunctionType())
+ return 1;
+
+ while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
+ T = cast<ArrayType>(T)->getElementType();
+
+ return getTypeAlign(T);
+ }
+
+ return 1;
+}
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 6d1d150c1c..49cc3201db 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -508,8 +508,8 @@ public:
private:
bool HandleCast(CastExpr* E);
- uint64_t GetAlignOfExpr(const Expr *E);
- uint64_t GetAlignOfType(QualType T);
+ unsigned GetAlignOfExpr(const Expr *E);
+ unsigned GetAlignOfType(QualType T);
};
} // end anonymous namespace
@@ -844,7 +844,7 @@ bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr());
}
-uint64_t IntExprEvaluator::GetAlignOfType(QualType T) {
+unsigned IntExprEvaluator::GetAlignOfType(QualType T) {
const Type *Ty = Info.Ctx.getCanonicalType(T).getTypePtr();
// __alignof__(void) = 1 as a gcc extension.
@@ -873,8 +873,17 @@ uint64_t IntExprEvaluator::GetAlignOfType(QualType T) {
return Info.Ctx.getTypeAlign(Ty) / CharSize;
}
-uint64_t IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
-
+unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
+ E = E->IgnoreParens();
+
+ // alignof decl is always accepted, even if it doesn't make sense: we default
+ // to 1 in those cases.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return Info.Ctx.getDeclAlign(DRE->getDecl());
+
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return Info.Ctx.getDeclAlign(ME->getMemberDecl());
+
return GetAlignOfType(E->getType());
}