Add path expanded flag (#12820)

* Add expanded flag to ConcreteAttributePath

And set it from the AttributePathExpandIterator.

* Ensure expanded flag is not sliced

Derived "copy" constructors that take the base can slice it. Fix that.

* Remove expanded flag from equality test

It's more of a metadata thing anyways.
diff --git a/src/app/AttributePathExpandIterator.cpp b/src/app/AttributePathExpandIterator.cpp
index 505997e..02b0996 100644
--- a/src/app/AttributePathExpandIterator.cpp
+++ b/src/app/AttributePathExpandIterator.cpp
@@ -117,6 +117,8 @@
 {
     for (; mpClusterInfo != nullptr; (mpClusterInfo = mpClusterInfo->mpNext, mEndpointIndex = UINT16_MAX))
     {
+        mOutputPath.mExpanded = mpClusterInfo->HasAttributeWildcard();
+
         if (mEndpointIndex == UINT16_MAX)
         {
             // Special case: If this is a concrete path, we just return its value as-is.
diff --git a/src/app/ConcreteAttributePath.h b/src/app/ConcreteAttributePath.h
index 4ade1b1..d1f4691 100644
--- a/src/app/ConcreteAttributePath.h
+++ b/src/app/ConcreteAttributePath.h
@@ -26,6 +26,9 @@
 
 /**
  * A representation of a concrete attribute path. This does not convey any list index specifiers.
+ *
+ * The expanded flag can be set to indicate that a concrete path was expanded from a wildcard
+ * or group path.
  */
 struct ConcreteAttributePath
 {
@@ -41,6 +44,7 @@
     }
 
     EndpointId mEndpointId   = 0;
+    bool mExpanded           = false; // NOTE: in between larger members
     ClusterId mClusterId     = 0;
     AttributeId mAttributeId = 0;
 };
@@ -54,9 +58,7 @@
 {
     ConcreteReadAttributePath() {}
 
-    ConcreteReadAttributePath(const ConcreteAttributePath & path) :
-        ConcreteReadAttributePath(path.mEndpointId, path.mClusterId, path.mAttributeId)
-    {}
+    ConcreteReadAttributePath(const ConcreteAttributePath & path) : ConcreteAttributePath(path) {}
 
     ConcreteReadAttributePath(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId) :
         ConcreteAttributePath(aEndpointId, aClusterId, aAttributeId)
@@ -90,6 +92,8 @@
 
     ConcreteDataAttributePath() {}
 
+    ConcreteDataAttributePath(const ConcreteAttributePath & path) : ConcreteAttributePath(path) {}
+
     ConcreteDataAttributePath(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId) :
         ConcreteAttributePath(aEndpointId, aClusterId, aAttributeId)
     {}
diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp
index c32d439..b178c78 100644
--- a/src/app/util/ember-compatibility-functions.cpp
+++ b/src/app/util/ember-compatibility-functions.cpp
@@ -359,8 +359,9 @@
                                  AttributeValueEncoder::AttributeEncodeState * apEncoderState)
 {
     ChipLogDetail(DataManagement,
-                  "Reading attribute: Cluster=" ChipLogFormatMEI " Endpoint=%" PRIx16 " AttributeId=" ChipLogFormatMEI,
-                  ChipLogValueMEI(aPath.mClusterId), aPath.mEndpointId, ChipLogValueMEI(aPath.mAttributeId));
+                  "Reading attribute: Cluster=" ChipLogFormatMEI " Endpoint=%" PRIx16 " AttributeId=" ChipLogFormatMEI
+                  " (expanded=%d)",
+                  ChipLogValueMEI(aPath.mClusterId), aPath.mEndpointId, ChipLogValueMEI(aPath.mAttributeId), aPath.mExpanded);
 
     if (aPath.mAttributeId == Clusters::Globals::Attributes::AttributeList::Id)
     {