Summary: We mark these decls as invalid.
Reviewers: sammccall
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77037
/// Whether this type is a variably-modified type (C99 6.7.5).
VariablyModified = 8,
- // FIXME: add Error bit.
+ /// Whether this type references an error, e.g. decltype(err-expression)
+ /// yields an error type.
+ Error = 16,
None = 0,
- All = 15,
+ All = 31,
DependentInstantiation = Dependent | Instantiation,
- LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
};
};
using TypeDependence = TypeDependenceScope::TypeDependence;
return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
translate(V, Instantiation, TypeDependence::Instantiation) |
translate(V, Dependent, TypeDependence::Dependent) |
+ translate(V, Error, TypeDependence::Error) |
translate(V, VariablyModified, TypeDependence::VariablyModified);
}
return static_cast<TypeDependence>(TypeBits.Dependence);
}
+ /// Whether this type is an error type.
+ bool containsErrors() const {
+ return getDependence() & TypeDependence::Error;
+ }
+
/// Whether this type is a dependent type, meaning that its definition
/// somehow depends on a template parameter (C++ [temp.dep.type]).
bool isDependentType() const {
auto RunSignatureHelp = [&]() {
ParsedType TypeRep =
Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
- assert(TypeRep && "invalid types should be handled before");
- QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+ QualType PreferredType;
+ // ActOnTypeName might adjust DeclaratorInfo and return a null type even
+ // the passing DeclaratorInfo is valid, e.g. running SignatureHelp on
+ // `new decltype(invalid) (^)`.
+ if (TypeRep)
+ PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
CalledSignatureHelp = true;
return PreferredType;
};
break;
}
+ // FIXME: we want resulting declarations to be marked invalid, but claiming
+ // the type is invalid is too strong - e.g. it causes ActOnTypeName to return
+ // a null type.
+ if (Result->containsErrors())
+ declarator.setInvalidType();
+
if (S.getLangOpts().OpenCL &&
S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
declarator.setInvalidType(true);
// FIXME: store initializer even when 'auto' could not be deduced.
// Expressions with errors currently do not keep initializers around.
-// CHECK: `-VarDecl {{.*}} invalid e 'auto'
+// CHECK: -VarDecl {{.*}} invalid e 'auto'
auto e = bar();
+
+// Error type should result in an invalid decl.
+// CHECK: -VarDecl {{.*}} invalid f 'decltype(<recovery-expr>(bar))'
+decltype(bar()) f;
-// RUN: %clang_cc1 -verify -fsyntax-only %s
-void foo(); // expected-note {{requires 0 arguments}}
+// RUN: %clang_cc1 -verify -fsyntax-only -fno-recovery-ast %s
+// RUN: %clang_cc1 -verify -fsyntax-only -frecovery-ast %s
+
+void foo(); // expected-note 2{{requires 0 arguments}}
class X {
decltype(foo(42)) invalid; // expected-error {{no matching function}}
};
// Should be able to evaluate sizeof without crashing.
static_assert(sizeof(X) == 1, "No valid members");
+
+class Y {
+ typeof(foo(42)) invalid; // expected-error {{no matching function}}
+};
+// Should be able to evaluate sizeof without crashing.
+static_assert(sizeof(Y) == 1, "No valid members");
StringRef Code = R"cpp(
auto x = decltype(&1)(^);
auto y = new decltype(&1)(^);
+ // GNU decimal type extension is not supported in clang.
+ auto z = new _Decimal128(^);
)cpp";
EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
}
+
} // namespace