Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7697,6 +7697,26 @@ NamedDecl *Sema::ActOnVariableDeclarator(
LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope, ArrayRef<BindingDecl *> Bindings) {
QualType R = TInfo->getType();

if (const AutoType *AT = R->getContainedAutoType()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this as a fixup seems wrong to me here. IF we wanted to merge these, we should do so at the root.

Also, your tests dont' really seem related to this, what is going on?

if (AT->isConstrained()) {
bool IsInDependentContext = DC->isDependentContext();
bool ShouldBeDependent = IsInDependentContext && !AT->isDeduced();

if (ShouldBeDependent != AT->isDependentType()) {
QualType CanonAuto = Context.getAutoType(
AT->isDeduced() ? AT->getDeducedType() : QualType(),
AT->getKeyword(),
ShouldBeDependent,
false,
AT->getTypeConstraintConcept(),
AT->getTypeConstraintArguments());

R = Context.getQualifiedType(CanonAuto, R.getQualifiers());
TInfo = Context.getTrivialTypeSourceInfo(R, D.getBeginLoc());
}
}
}
DeclarationName Name = GetNameForDeclarator(D).getName();

IdentifierInfo *II = Name.getAsIdentifierInfo();
Expand Down
92 changes: 92 additions & 0 deletions clang/test/SemaCXX/constrained-auto-type-consistency.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// expected-no-diagnostics
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s

namespace std {
template<typename T>
concept integral = __is_integral(T);

template<typename T>
concept floating_point = __is_floating_point(T);
}

// Constrained auto in abbreviated function template
void find(auto value) {
std::integral auto var = value;
}

// Constrained auto at namespace scope (non-dependent context)
// Should be deduced immediately
std::integral auto globalVar = 42;

// Multiple constrained autos in template function
template<typename T>
void multipleConstrainedAutos(T value) {
std::integral auto x = 10;
std::floating_point auto y = 3.14;
std::integral auto z = value; // dependent on T
}

// Constrained auto with qualifiers
void testQualifiers(auto value) {
const std::integral auto cv1 = value;
std::integral auto const cv2 = value;
}

// Nested constrained auto
void testNested(auto outer) {
auto lambda = [](auto inner) {
std::integral auto nested = inner;
return nested;
};

std::integral auto result = lambda(outer);
}

// Constrained auto with references
void testReferences(auto value) {
std::integral auto& ref = value;
const std::integral auto& cref = value;
}

// Regular unconstrained auto (should not be affected by the fix)
void testUnconstrainedAuto(auto value) {
auto regular = value;
decltype(auto) decl_auto = (value);
}

// Constrained auto in class template member
template<typename T>
struct Container {
void process(auto item) {
std::integral auto local = item;
}
};

// Constrained auto deduction from function call
std::integral auto getInteger() { return 42; }

void testFunctionReturn(auto param) {
std::integral auto fromFunc = getInteger();
std::integral auto fromParam = param;
}

// Ensure the fix doesn't break normal non-template constrained auto
void normalFunction() {
std::integral auto x = 100;
// This should be immediately deduced to int, not dependent
}

// Instantiate templates to verify no crashes
void instantiateAll() {
find(42);
multipleConstrainedAutos(5);
testQualifiers(7);
testNested(8);
int val = 10;
testReferences(val);
testUnconstrainedAuto(11);
Container<int> c;
c.process(12);
testFunctionReturn(13);
normalFunction();
}