diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -71,8 +71,10 @@ if (!D) return Deps; for (const auto *I : D->specific_attrs()) { + if (I->isAlignmentErrorDependent()) + Deps |= ExprDependence::Error; if (I->isAlignmentDependent()) - return Deps | ExprDependence::ValueInstantiation; + Deps |= ExprDependence::ValueInstantiation; } return Deps; } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -396,8 +396,10 @@ const AttrVec &V = getAttrs(); ASTContext &Ctx = getASTContext(); specific_attr_iterator I(V.begin()), E(V.end()); - for (; I != E; ++I) - Align = std::max(Align, I->getAlignment(Ctx)); + for (; I != E; ++I) { + if (!I->isAlignmentErrorDependent()) + Align = std::max(Align, I->getAlignment(Ctx)); + } return Align; } diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -97,4 +97,9 @@ void test(int x) { foo.abc; foo->func(x); -} \ No newline at end of file +} + +// CHECK: |-AlignedAttr {{.*}} alignas +// CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors +// CHECK-NEXT:| `-UnresolvedLookupExpr {{.*}} 'invalid' +struct alignas(invalid()) Aligned {}; diff --git a/clang/test/SemaCXX/invalid-aligned-attr.cpp b/clang/test/SemaCXX/invalid-aligned-attr.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/invalid-aligned-attr.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -frecovery-ast -verify %s +// RUN: %clang_cc1 -verify %s + +struct alignas(invalid()) Foo {}; // expected-error {{use of undeclared identifier}} + +constexpr int k = alignof(Foo); diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -481,6 +481,7 @@ void writeAccessors(raw_ostream &OS) const override { OS << " bool is" << getUpperName() << "Dependent() const;\n"; + OS << " bool is" << getUpperName() << "ErrorDependent() const;\n"; OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n"; @@ -511,6 +512,15 @@ << "Type->getType()->isDependentType();\n"; OS << "}\n"; + OS << "bool " << getAttrName() << "Attr::is" << getUpperName() + << "ErrorDependent() const {\n"; + OS << " if (is" << getLowerName() << "Expr)\n"; + OS << " return " << getLowerName() << "Expr && " << getLowerName() + << "Expr->containsErrors();\n"; + OS << " return " << getLowerName() + << "Type->getType()->containsErrors();\n"; + OS << "}\n"; + // FIXME: Do not do the calculation here // FIXME: Handle types correctly // A null pointer means maximum alignment